zoukankan      html  css  js  c++  java
  • 基于Oracle的SQL优化(崔华著)-学习笔记

    201704171025

    01、

    列rows记录的就是执行计划中每一个执行步骤所对应的Cardinality的值

    列Cost(%CPU)记录的就是执行计划中的每一个执行步骤对应的成本

    02、

    Computed Cardinality=Original Cardinality * Selectivity

    03、简单谓词连接

    04、B树索引

     05、索引连接方式

    索引唯一扫描
      是针对唯一索引的扫描,它仅仅适用于where条件里是 等值查询的目标sql。因为扫描的对象时唯一性索引,索引索引唯一性扫描的结果之多返回一条记录

    索引范围扫描
      适用于所有类型的B树索引。
      当扫描对象时唯一性索引时,此时目标sql的where条件一定是范围查询(谓词条件为 between 、<、>);
      当扫描对象是非唯一性索引时,此时目标sql的where条件没有限制(可以是等值,也可以是范围查询)
     
    索引全扫描
      适用于所有类型的B树索引。
      要扫描目标索引所有叶子快的所有索引行。索引全扫描需要扫描目标索引的所有叶子快。
      oracle在做索引全扫描时只需要访问必要的分支块等位到鱼尾该索引最左边的叶子快的第一行索引行,就可以利用该索引椰子块之间的双向指针链表,从左至右一次扫描叶子块的所有索引行
     
    索引快速全扫描
      只适合于CBO
      可以单块读可以多快读
      结果集不一定是有序的。因为FFS 时 oracle根据索引行在磁盘上的 物理存储位置 扫描,而不是根据索引行的逻辑顺序扫描。因此结果不一定有序  
     
    索引跳跃式扫描
      仅仅适用于那些目标索引前导列的distinct值数量较少、后续非前导列的可选择性有非常好的情形。因为索引跳跃式扫描的执行效率一定会随着目标索引前导列的distinct值数量的递增而递减
     

    06、

    hint 强制使用9i版本
      /*+optimizer_feature_enable(9.2.0) */

    201704172148

    --嵌套循环连接的优缺点和应用场景

    对于嵌套循环连接的优缺点及适用场景,我们有如下总结。
    从上述嵌态循环连接的具体执行过程可以看出:如果驱动表所对应的驱动结果集的记录数较少,同时
    在被驱动表的连接列上又存在唯一性索引(或者在被驱动表的连接列上存在选择性很好的非唯一索引),那么此时使用嵌套循环连接的执行效率就会非常高;但如果驱动表所对应的驱动结果集的记录很多,即便在被驱动表的连接列上存在索引,此时使用嵌套循环连接的执行效率也不会高。
    只要驱动结果集的记录数较少,那就具备了做嵌套循环连接的前提条件,而驱动结果集是在对驱动表应用了目标sql指定的谓词条件)所得到的结果集,所以大表也可以作为嵌套循环连接的驱动表。关键看目标SQL中指定的谓词条件(如果有的话)能否将结果集降下来。


    嵌套循环连接有其他方式所没有的一个优点:嵌套循环连接可以实现快速响应
     
    对表收集统计信息
    exec dbms_stats.gather_table_stats(ownname=>'owner_name',tabname=>'tab_name',cascade=>true,no_invalidate=>false,degree=>4);
     
    20170418

    1021
    本质上SQL ID和SQL HASH VALUE是一回事,它们是可以互相转换的,这也是方法
    BMS_XPLAN.DISPLAY CURSOR所传入的第一个参数的值可以是SQL ID,也可以是SQL HASH VALUE
    SQL> select   lower(trim(13yfu3wh150aqt!))sql id, trunc(mod (sum((instr(10123456789abedfghikmnpqrstuvwxyz'            niintgsett)),level,1))-1)*power(32,1ength(trin( 3yfuswhis0asth   nnntsubstr(lower(trim('3yfu3whis0aqt')),level,1))-1)'pove    nint-level)),power(2,32)))hash value
     from dual
     
     
    1045
    执行 select * from table(dbms_xplan.display_awr('sql_id')) ,用于查看指定sql的历史执行计划

    1103 oradebug
    oradebug setmypid
    oradebug event 10046 trace name context forever,1evel 12;

    select statements

    oradebug tracefile_name

    oradebug event 10046 trace name context off

    tkprof ......trc

    cr :consistent reads
    pr :physical reads


    1411
     
     


    先从最开头一致持续往右看,直到看到最右边的并列的地方;
    对于不并列的,靠右的先执行;
    如果见到并列的,就从上往下看。对于并列的部分,靠上的先执行

    TABLE ACCESS FULL
    BUFFER SORT


    Plan hash value:2105702960
    ------------------------------------------------------------------------------------------------------------------
    |Id  | Operation                       | Name               | Rowa | Bytes | Cost(%CPU) | Time        |
    | 0  | SELBCT STATEMENT                |                    |      |       |  3082(100))|             |
    | 1  |  SORT AGGREGATE                 |                    |    1 |   54  |            |             |
    | 2  |   CONCATENATION                 |                    |      |       |            |             |
    | 3  |    MERGE JOIN CARTESIAN         |                    | 470K |   24M |   1969(4)  |   00:00:24  |
    | 4  |     TABLE ACCESS PULL           |OWBATN              |   1  |   34  |    851(5)  |   00:00:11  |      
    | 5  |     BUFFER SORT                 |                    |  316K|  6175K|    1118(3) |   00:00:14  |
    | 6  |      TABLE ACCB88 FULL          |UPLTER              |  316K|  6175K|    1118(3) |   00:00:14  |
    | 7  |    FILTER                       |                    |      |       |            |             |
    | 8  |    HASH JOIN                    |                    | 37522|  1978K|   1109(6)  |   00:00:14  |
    | 9  |     TABLE ACCESS PULL           |OWBATN              | 20956|   695K|   852(5)   |   00:00:11  |
    | 10 |     INDEX FAST FULL SCAN        |IDX_UPLTER_UTETKT   |  316K|  6175K|   246(6)   |  00:00:03   |
    | 11 |    SORT AGGRBGATE               |                    |   1  |   38  |            |             |
    | 12 |     TABLE ACCES8 BY INDEX ROWID | UPLTER             |   1  |   30  |     4(0)   | 00:00:01    |
    | 13 |       INDEX RANGE scAN           | IDx_UPLTER_UTETKT  |   2  |       |     3(0)   |  00:00:01   |
    ·13
    eedieate Information (identitied by operetton ttii
    otp,on "O"."OATE8m"="F"OR "o","oATPgn"-'I”))

    id=0 SELBCT STATEMENT 开始往右找,一直找到 id=4 TABLE ACCESS PULL   |OWBATN   和 id=5 BUFFER SORT 并列,由于并列的部分靠上的先执行(buffer soft不可能先执行,因为没任何理由上去就是一个 buffer sort啊),所以 id=4 TABLE ACCESS PULL   |OWBATN 第一个执行,同 id=5 BUFFER SORT 相比,   id= 6  |      TABLE ACCB88 FULL          |UPLTER  靠右,因此
    id= 6  |      TABLE ACCB88 FULL          |UPLTERid=5 BUFFER SORT  先执行,
     
    id=4    TABLE ACCESS PULL   |OWBATN   第1个执行
    id= 6        TABLE ACCB88 FULL    |UPLTER 第2个执行
    id=5 BUFFER SORT   第3个执行
    id=3    MERGE JOIN CARTESIAN  第4个执行
    id=9       TABLE ACCESS PULL           |OWBATN  第5个执行
    id=10      INDEX FAST FULL SCAN        |IDX_UPLTER_UTETKT  第6个执行
    id=8      HASH JOIN              第7个执行
    id=13        INDEX RANGE scAN           | IDx_UPLTER_UTETKT  第8个执行
    id=12      TABLE ACCES8 BY INDEX ROWID | UPLTER    第9个执行
    id=11     SORT AGGRBGATE  第10个执行 
    id=7      FILTER  第11个执行
    id=2     CONCATENATION1  第12个执行
    id=1     SORT AGGREGATE   第13个执行
    id=0   SELBCT STATEMENT  第14个执行
     
     

    XPLAN包查看执行计划的执行顺序  


    列的属性为  null,那么该字段可能会存  null类型的数据。因此 如果按照 访问索引的方式访问 可能会漏掉数据。 索引上不会有null数据

    dbms_xplan.display_cursor(null,null,'advanced')  弊端多多啊,必须在执行完sql之后 马上执行这个操作。才可以看到执行计划         太被动

    比如 表t的索引列为a,然后我执行查询:select a,b from t where a = 'xxx';
    这样的话,靠a上的索引提供不了查询所要的数据a+b,所以要去表中找,这个过程叫做回表?
     
    2118
    10032事件 专对 排序
     
    20170419
    0903
    whenever sqlerror exit sql.sqlcode;

    dbms_sqltune.import_sql_profile

    索引聚簇因子
    更新聚簇因子 exec dbms_stats.set_index_stats(ownname=>'user_name',indname=>'index_name',clstfct=>24000000,no_invalidate=>false)
    查询聚簇因子 select idx1.index_name,idx1.clustering_factor from dba_indexes idx1

    1045
    cursor
    oracle数据库中的shared cursor 又可细分为 parent cursor 和child cursor 这两种类型。通过查询视图 v$sqlarea 可查看 parent cursor,v$sql 可查看child cursor

    Parent Cursor 和 Child Cursor的结构是一样的(它们都是以库缓存对象句柄的方式缓存在库级存中,
    Namespace属性的值均为CRSR),它们的区别在于目标SQL的SOL文本会存储在其Parent Curser所对应的缓存对象句柄的属性Name中(Child Cursor对应的库缓存对象句柄的Name属性值为空,这意味着只有通过
    Parent Cursor才能找到相应的Child Cursor),而该SQL的解析树和执行计划则会存储在其Child Cursor所对应的库缓存对象句柄的Heap6中,同时Oracle会在该SQL所对应的Parent Cursor的Heap 0的的Child table中,
    存储从属于该Parent Cursor的所有Child Cursor的库缓存对象句柄地址(这意味着Oracle可以通过访问 Paren cursor
    中的Child table而依次顺序访问从属于该Parent Cursor的所有Child Cursor)。

    parent cursor 会存储该sql的sql文本,child cursor 会存储 该sql对应的解析数和执行计划


    1415 errorstack
    alter session set events'immediate trace name errorstack level 3'


    隐式游标
     sql%FOUND  true/false
     sql%NOTFOUND  true/false  sql语句被执行成功后受影响的行数是否是0
     sql%isopen   隐式游标是否处于open状态   恒为 false
     sql%rowcount 一条sql语句成功执行后受影响而改变的记录的数量
     
    1524
    参考游标的定义方式以下四种

    第一种方式:
    type typ_cur_emp is ref cursor return emp%rowtype;
    cur_emp  typ_cur_emp;

    第二种方式:
    type typ_result is record(ename emp,ename%type,sal emp.salstype;
    type typ_cur strong is ref cursor return typ_result;
    cur emp typ cur_stong;

    第三种方式:
    tvpe typ_cur weak is ref cursor;
    cur_emp typ_cur_weak;

    第四种方式:
    cur emp SYS_REFCURSOR;
    上述范例HL/SQL代码用四种不同的方式分别定义了同一个参考游标ctr.emm

    1559
    PL/SQL中select语句的绑定变量典型用法
    execute immediate 'select ename from emp where empno=:1' using 7369;

    1608
    PL/SQL代码中批量fetch对应的语法:
    fetch cursor_name bluk collect into [自定义的数组] <limit 数字[建议值通常 1000]>


    forall i in 1..[自定义数组的长度]   --forall 表示一次执行一批sql
     execute immediate [带绑定变量的目标sql]  using [对应绑定变量的输入值]
     
     
    PLSQL中使用批量绑定的范例代码为如下所示,
    declare

     cur_emp sys refcursor;
     ve_sql varchar2(4000);
     expe namelist ie table of varchar2(10);
     enames namelist;
     CN_BATCH_SIZE constant pls_integer :=1000;
    begin
     vc_sql :='select ename  from emp where empno>:1';
     open cur_emp for vc_sql using 7900;

    loop
    feteh cur_emp bulk collect into enames linit CN_BATCH_SIZE;

    for i in 1..enames.count loop
    dbms_output.put_line(enames(i));
    end loop;

    exit when enames.count< CN_RATCH_SIZE;
    end loop;
    close cur_emp;
    end;
    /


    1709
    index fast full scan 会扫描所有的索引叶子块
     
     
     1723
    对于目标soL(即即 seleet count(*) fom tl where object_id  between :x and :y)而言,其where条件的selectivity
    和Cardinality的计算公式为如下所示示
    Cardinality=NUM_Rows*Selectivity
    selectivity=((y-x)/(HIGH_VALUE-LOW_VALUE)+2/NUM_DISTINCT)*Nu11_Adjust
    Nu11_Adjust=(NUM ROWS-NUM_NULLS)/NUM_ROWS


    NUM_Rows表示目标列所在表的记录总数
    LOW_VALUE 目标列的最小值
    HIGH_VALUE 目标列的最大值
    NUM_DISTINCT 目标列的 distinct值的数量
    NUM_NULLS 目标列的NULL列的数量
     
    2045
    从如下查询结果可以看到,对应于上述计算公式的LOW_VALUE的值为C103,
    HIGH_VALUE的值为C309395E,NUM_DISTINCT的值为72,387,NUM_NULLS的值为2;

    select 1ow_value,high_value,num_distinct,num_nulls from dba_tab_col_statistics
    where  owner='SCOTT' and table_name='T1' and column_name='OBJECT_ID';

    LOW_VALUE HTCH_VATUE NUM_DTSTINCT NUM_NULLS
    ----------------------------------------------
    c103     C309395e      72387   2


    从如下查询结果可以看到,HIGH_VALUE的值C309395E实际上就等于85,093;
    SQL> select max(object_id),dump(min(object_id),16)  from ti ;

    MAX(OBJECT_ID)   MAX (OBJECT ID) DUMP(MAx(OBJECT_ID),16)
    85693      Typ=2 Len=4: c3,9,39,5e


    从如下查询结果可以看到,LOW_VALUE的值C103实际上就等于2
    SQL> select min(object_id),dump(min(object_id),16)  from ti ;
    MIN(OBJECT_ID)   MIN (OBJECT ID) DUMP(MAx(OBJECT_ID),16)
    2     Typ=2 Len=2: c1,3

    查询到的 NUM_ROWS、LOW_VALUE、HIGH_VALUE、NUM_DISTINCT、NUM_NULLS 和 x、y的值代入计算公式。



    2111 删除sql的 shared cursor
    exec sys.dbms_shared_pool.purge([address],[hash_value],'c');

    2215
    select  tab.ADDRESS,tab.BIND_NAME,tab.POSITION,tab.DATATYPE,tab.MAX_LENGTH  from v$sql_bind_metadata tab


    2217 批量绑定时如何处理错误
    bulk_errors exception;
    paragma exception_init(bulk_errors,-24381);

    type typ_errorindex is table of number index by binary_integer;
    errorindexs typ_errorindex;
    type typ_errorcode is table of varchar2(50) index by binary_integer;
    errorcodes typ_errorcode;

    exception
    when bulk_errors then
      for i in 1..sql%bulk_exceptions.count() loop
       errorindexs(j):=sql%bulk_exceptions(j).error_index;
       errorindexs(j):=-sql%bulk_exceptions(j).error_index;
     
    20170420

    0934
    Oracle10g及后续的版本中,Oracle会自动收集直方图统计信息。直方图统计信息 是对于单个列的

    0946
    v$sql_cs_statistics 用于显示指定 child cursor中存储的runtime统计信息
    v$sql_cs_selectifity 用于显示指定的、已经被标记为 Bind Aware的 Child Cursor中存储的含绑定变量的谓词条件对应的可选择率的范围

    0956
    收集直方图统计信息
    exec dbms_stats.gather_table_stats(ownname=>'SCOTT',tabname=>'T1',estimate_percent=>100,cascade=>true,method_opt=>'for all columns size auto',no_invalidate=> false);
    dbs_tab_col_statistics

    1009
    再次以目标SQL对应的SQL_ID去查询视图VSSQL:
    soL> select child_number,executions,buffer_gets,is bind_sensitive bs,is bind_aware ba,
    is shareable SH,plan_hash_value from v$seql where sql id=179g1p919t7x4u”)
    BUFFER GETS BS BA SH BLAN_HASH_VALUE
    EXECUTIONS
    CHILD NUMBER



    1029
    在目标列有Frequency类型直方图的前提条件下,如果对目标列等值查询条件,且在查询条件的输入值等于该类的实际值时,谓词条件的可选择率计算公式如下所示:

    selectivity=Bucketsize /NUM_ROMS
    上述计算公式启用了绑定变量就探,目标列有Frequency类型的直方图,对日标列添加等值查询条件,且
    查询条件的输入值等于该列的某个实际值时的计算。
     NUM_ROWS  表示目标列所在表的记录数。
     BucketSize表示目标列的某个实际值所对应的记录致。
     
    1051  -一定得搞清楚   child_number 可以根据sql_id 找到该sql所有的 child_number
    child curor的可选择率范围
    select child_number,predicate,range_id,low_high from v$sql_cs_selectivity where sql_id='xxxx';

    v$sqlarea



    1647
    子查询展开,执行效率
    in  外部结果集条数 有 N,其实执行效率会把外部查询全部执行,然后根据内部查询的结果 去外部结果中 遍历
    /* no_merge(view_name) */  不合并视图

    20170420

    2124
    参数star_transformation_enabled 用于控制是否启用星型转换
     
    20170421

    0939
    在Oracle11gR2之前,把某个据不分区索引的状态设为unusable后,会导致所有原本可以使用该局部分区索引的查询语句都无法正常使用该局部分区索引
    alter index index_name modify parartition p12 unusable; 索引的单个分区索引 失效
    alter index index_name rebuild partition p12; 重建该分区索引,恢复可用状态

    1005
    表移除
    select ename from emp,dept where emp.deptno=dept.deptno;
    表empde  列deptno 属性为 not null,而在列deptno 和主表dept的主键列存在一个名为pk_deptno的外键。对于该外键而言,表emp是子表,表dept是主表。即 对于子表emp的列deptno而言,主表dept中一定存在与之对应的匹配记录。因此
    以上sql相当于 select ename from emp
    博大精深的 cbo啊


    1013
    emp.deptno=dept.deptno(+)   外连接哦

    1024
    select * from emp where deptno in (10)
    union all
    select * from emp where mgr in (7782) and lnnvl(deptno in (10))
    函数LNNVL 作用:排除 mgr in (7782) and deptno in (10)这种情形

    1122
    awr sql report
    stat_name         statement_total     per_exection
    elapsed_time(ms)                       637922      
    exections            66(次)
    buffer gets                              222222(个)


    1439
    一定要记住哦,对系统内部表使用dbms_stats包收集统计信息哦。如下
    exec dbms_stats.gather_table_stats(ownname=>'SYS',tabname=>'X$BH');

    从Oracle10g开始,创建索引之后Oracle会自动收集目标索引的统计信息

    删除索引的统计信息
    analyze index index_name delete statistics;

    对表t2收集统计信息,并且是 以 估算模式,采样比例是 15%
    analyze table t2  estimate statistics sample 15 percent for table;

    对表t2收集统计信息,并且以  计算模式
    analyze table t2 compute statistics for table;

    对表t2 的列 col1,col2 收集统计信息,以 计算模式
    analyze table t2 compute statistics for column col1,col2;

    记住哦,对同一个对象 新的analyze命令会擦除 之前的analyze的结果

    同时对表t2和 列 col1、col2 收集统计信息
    analyze table t2 compute statistics for table for columns col1,col2;

    以计算模式对索引 idx02 收集统计信息
    analyze index idx02 compute statistics;

    一次性的以  计算模式 收集表t2、表t2的所有列和表t2上的所有索引的统计信息,如下:
    analyze table t2 compute statistics;

    以估算模式对条t2收集统计信息,采样比例是15%
    exec dbms_stats.gather_table_stats(ownname=>'SCOTT',tabname=>'T2',estimate_percent=>15,method_opt=>'FOR TABLE',cascade=>false);

    删除表t2、所有列、所有索引的统计信息
    exec dbms_stats.delete_table_stats(ownname=>'SCOTT',tabname=>'T2')

    一次性以计算模式收集表t2、所有列、所有索引的统计信息
    exec dbms_stats.gather_table_stats(ownname=>'SCOTT',tabname=>'T2',ESTIMATE_PERCENT=>100,CASCADE=TRUE);

    1542
    analyze 命令不能正确收集分区表的统计信息,而DBMS_STATS包

    1548
    dbms_stats包可以  并行收集表的统计信息哦  degree
    exec dbms_stats.gather_table_stats(ownname=>'SCOTT',tabname=>'T2',cascade=>true,estimate_percent=>100,degree=4);

    dbms_stats只能收集与cbo相关的统计信息,而与cbo无关的额外信息无法收集。比如 行迁移/行链接。analyze 可以哦
    比如:analyze table table_name list chained rows into xxx;
    analyze index index_name validate structure;


    1621
    数据典中的字段NUM ROWS存储的就是目标表的记录数,目标表的记录数是计算结果集的基础,而结果集的Cardinality则往往直接决定了CBO计算的成本值。

    数据字典中的字段BLOCKS存储的就是目标表表块的数量,即目标表的数据所占用数据块的数量,目标表表块的数量会直接决定CBO计算出来的对目标表做全表扫描的成本,目标表表块的数量越大,则对目标表走全表扫描的成本值就会越大。

    数据字典中的字段AVG_ROW_LEN存储的就是目标表的平均行长度。平均行长度的计算方法是用目标表的所有行记录所占用的字节数(不算行头)除以目标表的总行数,它可能会被Oraele,用来计算目标表对应的结果集所占用内存的大小

    1650
    --2.查找表的历史统计信息
    select obj.object_name, oth.savtime, oth.rowcnt, oth.analyzetime,oth.blkcnt,oth.avguln
      from sys.WRI$_OPTSTAT_TAB_HISTORY oth, dba_objects obj
     where oth.obj# = obj.object_id and obj.object_name='EMP' --请修改表名字
     order by oth.analyzetime desc nulls last;
     

    1507
    上述数据字典中的字段CLUSTERNG FACTOR.存储的就是目标索引的聚簇因子,聚族因子是指按照然索引键值排序和存储于对应表中的数据行的存储顺序的相似程度。

    上述数据字典中的字段DiSTRNCT KEYS存储的就是目标索引的索引键值的disinct值的数量。对于唯一性索引而言,在没有NULL值的情况下,DISTINCT.KEYS的值就等手对应表的记录数。

    上述数据字典中的字段AVG_LEAF_BLOCKS_PER_KEY存储的就是目标索引的每个distinct索引键值所占用的叶子块数量的平均值,对于唯一性索引而言,AVG_LEAF_BLOCKS_PER_KEY显然只会是1。

    上述数据字典中的字段AVG_DATA BLOCKS_PER_KEY存储的就是目标索引的每个distnet索引键值所对应表中的数据行所在数据块数量的平均值。

    上述数据字典中的字段NUM_ROWS存储的就是目标索引的索引行的数量。

    2109
    修改索引的聚簇因子  clstfct
    exec dbms_stats.set_index_stats(ownname=>'owner_name',indname=>'index_name',clstfct=>1000,no_invalidate=>false);

    hist_head$

    2125
    执行计划中Rows列的值表示CBO评估出来的对应执行步骤所返回结果集的行数
    cardinality=NUM_ROWS*selectivity
    Nul1_Adjust=(NUM——ROWS-NUM_NULLS)/NUM_ROWS
    selectivity=((HTGH_VALUE-VAL)/(HTCH_VALUE-Lo_VALUE))*Null——Adjust

    2140
    dba_hist_sqlstat

    2154
    检查目标表中 列的统计信息
    select  t1.low_value,t1.high_value  from dba_tab_col_statistics t1 where t1.table_name='EMP' and column_name='EMPNO'
    取出 low_value

    SQL> var temp date;
    SQL> exec dbms_stats.convert_raw_value('low_value',:temp);

    2208
    直方图 Histgrm是一种特殊的列统计信息,详细描述了目标列的数据分布情况。存储在数据字典基表 histgrm$;专门为了准确评估分布不均匀的目标列的可选择率、结果集的cardianlity。详细描述了目标列的数据分布情况,并将分布情况记录在数据字典里。

    2228 对 列收集直方图
    exec dbms_stats.gather_table_stats(ownname=>'owner_name',tabname=>'table_name',method_opt=>'for columns size auto column_name',cascade=>true);
    'for columns size auto column_name' 表示对目标表的列 column_name 收集直方图统计信息,auto 的含义是指让Oracle自行决定到底是否对列column_name收集的直方图是哪种类型的直方图

    oracle会关注目标表的某个列的使用情况,记录在 col_usage$
    select * from col_usage$;

    20170424
    0933
    dba_tab_col_statistics
    dba_tab_histograms 表的直方图相关信息

    0935
    文本型 ‘1’ 转换为 浮点数
     select dump(1,16) from dual;
      typ=96 len=1:31
      0x31右边补0一直补到15个字节的长度,再转换为十进制数
      select to_number('31000000000000000','XXXXXXXXXXXXXXXXX') from dual;
     
     
    0948
    删除列id上的直方图统计信息
    exec dbms_stats.gather_table_stats(ownname=>'owner_name',tabname=>'table_name',method_opt=>'for columns size 1 id',cascade=>true);
    注意此处的     1  表示对列 id收集直方图时使用的bucket的数量为1

    1010
    DBMS_STATS包中上述存储过程的输入参数METHOD_OPT可以接受如下的输入值:
    FOR ALL [INDEXED | HIDDEN] COLUMNs (size_clause]
    FOR CoLUMNS [size clause] column|attribute [size clause] [,columnlattzibute
    [size clause]..
    其中的size clause必须符合如下的格式:
    SIZE{integer | REPEAT | AUTo | SKEWONLY}
    size clause子句中各选项的含义如下所述。
    * interer.直方图的Bucket的数量,必须是在1~254的范围内,1表示删除该目标列上的直方图统计信息
    *REPEAT;只对已经有直方图统计信息的列收集宜方图统计信息,
    *auto  Oracle 自行决定是否对目标列收集直方图统计信息,以及使用哪种类型的直方图统计信息
    *SKEWONLY:只对数据分布不均衡的列收集直方图统计信息。

    1027
    select /*+cursor_sharing_exact_demo */ count(*) from t;
    v$sqlarea  version_count

    1034
    直方图统计信息实际上可以影响shared cursor是否能被共享

    1041
    null_adjust=(num_rows - num_nulls)/num_rows
    density(密度、基数)=1 / (2* num_rows * null_adjust)

    dba_tab_histograms

    1101
     select power(3296,2) from dual;

    POWER(3296,2)
    -------------
         10863616
         
    1122
    以下三忌:
    如果目标列的数据时均匀分布的,比如 主键列、唯一索引的列,根本不需要对这些列收集直方图统计信息     
    对于那些从没有在sql语句的where条件中出现的列,不管数据分布是否均匀,都无需对其收集直方图统计信息
    直方图统计信息可能会影响shared_cursor的共享
    在配置oracle10g引入的自动统计信息收集作业的时候,需要特别注意对直方图统计信息的收集策略

    1238
    全局统计信息对CBO来说是非常重要的,针对分区表的sql,除非查询条件先定了带访问的数据只在部分分区上,飞则大部分情况下都需要全局统计信息才能得到正确的执行计划
    只能由 dbms_stats来收集

    1246
    analyze命令对表t2以计算模式收集统计信息(计算模式会扫描目标对象的所有数据)
    analyze table t2 compute statistics;

    1249 查找某参数的默认值
    select dbms_stats.get_param('granularity') from dual;

    1252 删除表的统计信息
    exec dbms_stats.delete_table_stats(ownname=>'user_name',tabname=>'table_name')

    1255
    使用dbms_stats.gather_table_stats重新收集统计信息,参数granularity的值为 all,表示在t2的表级别、分区级别、子分区级别都收集全局统计信息
    exec dbms_stats.gather_table_stats(ownname=>'owner_name',tabname=>'table_name',estimate_percent=>100,granularity=>'ALL');

    1304
    analyze table table_name delete statistics;  只会删除子分区的统计信息

    1307
    analyze ... delete statistics.只级联删除子分区和分区的统计信息

    1310
    可以看到,ANALYZE…..DELETE STATISTICS命令只级联删除了子分区和分区上的统计信息

    综合上述测试结果我们可以发现,ANALYZE….DELETE STATISTiCS命令总是会删除子分区的统计信
    息,但是否能够级联删除分区级/表级的统计信息则取决于相应级别的GLOBAL_STATS的值。
    如分区表级/表级 的GLOBAL_STATS的值为YES,则不能级联删除;反之就可以级联删除。
    但要注意的是,ANALYZE  DELETE STATisTice命令不能跨级删除统计信息,比如分区的GLOBAL STATIS的值为YER,而表级的
    GLOBAL STATIS 的值为NO,则在使用ANALYZE…….DELETE STATISTiCS命令后表级的统计信息并不会被删除。
    另外,DBMS_STATS.DELETE_TABLE_STATISTICS 总是可以副除分区表上所有的三个级测的统计传。

    1316
    最后我们来总结一下在Oradke数据库中使用全局统计信息的注意事项。
    (1)应使用DBMS_STATS包来对分区表收集全局统计信息。
    (2)应使用DBMS_STATS包中的相关存储过程(如DBMS_STATS.DELETE_TABLE_STATS)来删除分区表的统计信息,尽量避免用ANALYZE命令,因为ANALYZE命令不一定能把分区表的统计信息删除干净
    (ANALYZE命令可能会导致部分统计信息并没有被删除)。
    (3)收集分区表的统计信息时应使用一致的GRANULARITY参数。如果不使用一致的GRANULARITY
    参数,比如开始用ALL,过一段时间用GLOBAL或PARTTTION,这样可能会导致在某些级别上的统计信息
    是过时的、不准确的。
    (4)由于ANALYZE命令只在最低一级收集统计信息,而高一级的统计信息则是由下级统计信息汇总和
    推导而来的,因此尽量不要使用ANALYZE命令来对分区表收集统计信息,特别是不要将ANALYZE命令与
    DBMS_STATS包联合使用在同一张分区表上,否则可能会导致该表在某些级别上的统计信息是过时的、不准确的。

    1325
    动态采样有如下两个方面的作用。
    (1)Oracle称如果使用了动态采样,则不管SQL语句中各列有什么样的关联关系,在大多数情况下,CBO
    都可以相对准确地估算出整个where条件的组合可选择率,进而能相对准确地估算出返回结果集的Cardinality
    (2)有一些应用在执行的过程中会创建一些临时表,然后会往这些临时表里插入一些中间结果,接着将这
    些临时表用于查询等操作,在执行完毕后会把这些临时表Drop掉或者Truncate其中的数据。这里的问题是
    当这些临时表参与查询等操作的时候,它们是没有统计信息的,这种情况下采用的执行计划有可能是低效的
    其至是错误的。而动态采样就可以在一定程度上解决这种因临时表没有统计信息而导致CBO选错执行计划的
    问题。


    1331
    参数OPTIMIZER_DYNAMIC_SAMPLING的值及含义

    level值及含义

    1338
    在“5.4.2聚族因子的含义及重要性”中提到索引范围扫描的成本计算公式为:
    IRS Cost=I/O Cost +CFU Cost
    I/O cost =Index Access I/o cost +Table Access I/o cost
    Index Access I/O Cost =BLEVEL+CEIL(#LEAF_BLocKS *IX_SEL)
    Table Access I/0 Cost=CEIL(CLUSTERING_FACTOR*IX_SEL_WTTH_FTLTERS)

    1400
    位表t2中有关联关系的列 n1 和 n2 创建一个组合咧

    declare
    cg_name varchar2(30);
    begin
    cg_name:=sys.dbms_stats.create_extended_stats('SCOTT','T2','(n1,n2)');
    dbms_ouptput.put_line(cg_name);
    end;
    /

    1413
    select col#,intcol#,distcnt,minimum,maximum,density from sys.hist_head$;

    1416
    exec dbms_stats.gather_table_stats(ownname=>'SCOTT',tabname=>'T2',method_opt=>'for columns(n1,n2) size auto',estimate_percent=>100);


    1436
    dbms_stats.gather_system_stats 收集数据库服务器的统计信息
    dbms_stats.delete_system_stats 删除数据库服务器的统计信息

    1. dbms_stats.gather_system_stats('start');开始收集系统统计信息
    2. 正常使用系统
    3. dbms_stats.gather_system_stats('stop');     停止收集系统统计信息

    1452
    系统统计信息会存储在表AUX_STATSS里。执行DBMS_STATS.GATHER_SYSTEM_STATS收集系统统计
    信息的时候,Oracle会在AUX STATSS里记录如下四个方面的信息。
    ·CPU的主频,单位是MHz(兆赫兹)。
    ·单块读的平均耗费时间,单位是ms(毫秒)。
    ·多块读的平均耗费时间,单位是ms(毫秒)。
    ·单次多块读所能读取的数据块的平均值。
    Orace 会记录目标数据库所在的数据库服务器上的单次多块读所能读取的数据块的平均值,这对计算
    全表扫描的成本带来了重大影响,因为在这种情况下MBDMSor 实际上就和
    DB_FILE_MULTIBLOCK_READ_COUNT的值没有关系了。

    1457
    sys.all_parameters

    1504
    oracle 11.2.0.1
    12:51:37 idle> show parameter multiblock;

    NAME                                 TYPE        VALUE
    ------------------------------------ ----------- ------------------------------
    db_file_multiblock_read_count        integer     128

    1522
    全表扫描  多快读(168)
    index range scan 单块读(1)

    1524
    修改单块读的平均耗费时间为 10ms
    exec dbms_skats.set_system_stats('sreadtim',10);

    修改多块读的平均耗费时间为 20ms
    exec dbms_skats.set_system_stats('mreadtim',20);
    1540
    dbms_stats包里的存储过程dbms_stats.gather_dictionary_stats、bms_stats.delete_dictionary_stats 分别用于一次性收集、删除所有数据字典统计信息

    1554
    DBMS_STATS包里的存储过程GATHER_FIXED_OBJECTS STATS和DELETE_FIXED_OBJECTS_STATS
    专用于一次性收集和删除所有的内部对象统计信息。
    上述两个存储过程的用法为如下所示。

    一次性地收集所有XS表的内部对象统计信息:
    sqL> exec dbms_stats.gather_fixed_objects_stats();
    PL/SoL procedure successfully completed

    一次性地删除所有X$表的内部对象统计信息:
    sql> exec dbms_stats.delete_fixed_objects_stats();
    BL/SoL procedure successfui1y compieted nnnnnniint

    收集单个x$(x$kccrsr) 表的对象统计信息
    exec dbms_stats.gather_table_stats(ownname=>'SYS',tabname=>'X$KCCRSR',estimate_percent=>100,cascade=>true);

    删除单个x$(x$kccrsr) 表的对象统计信息
    exec dbms_stats.delete_table_stats(ownname=>'SYS',tabname=>'X$KCCRSR');


    1656
    查看自动收集统计信息的job运行状态
    16:50:01 idle> select actual_start_date,job_name,status from (select * from dba_scheduler_job_run_details where job_name='GATHER_STATS_JOB' ORDER BY LOG_DATE DESC) where rownum <4;

    no rows selected


    1725
    sys.mon_mods_all$
    如果想马上看到目标表的insert 、update、delete,需要执行以下 dbms_stats包中的存储过程flush_database_monitoring_info;

    exec dbms_stats.flush_database_monitoring_info();
    select obj#,inserts,updates,deletes ,flags from sys.mon_mods_all$ where obj#=object_id;

    1733
    禁掉自动统计信息收集作业
    exec dbms_scheduler.disable('GATHER_STATS_JOB');


    只对存在直方图统计信息的列才收集直方图统计信息
    exec dbms_stats.set_param('METHOD_OPT','FOR ALL COLUMNS SIZE REPEAT');

    2135
    尽管如此,我们还是推荐一个统计信息收集作业采样比例的初始值;
    对于orede 11g及其以上的版本,收集统计信息的采样比例建议采用DBMS_STATS.AUTO_SAMPLE_SIZE.
    Oracle 110中的AUTO_SAMPLE_SIZE采用了全新的哈希算法,它既能保证在较短的时间内执行完又能保证收集到的统计信息
    接近采样比例为100%时的质量)。

    如果是Oracle 10g,继续采用DBMS_STATS.AUTO_SAMPLE_SIZE就不太合适了,因为这个自动采样比例在Oracle 10g里是非常小的一个
    Oracle 10g中将采样比例的初始值设为30%,然后根据目标SQL的实际执行情况再做调整
    如果是Oracle9i,我们建议将采样比例的初始值也设为30%,然后根据目标SQL的实际执行情况再做调整
    (5)建议使用DBMS_STATS包来对分区表收集全局统计信息,并且收集分区表的统计信息时应使用一致致
    的GRANULARITY参数,全局统计信息的收集方法和注意事项请见“5.6全局统计信息”。
    (6)建议要额外收集系统统计信息,但系统统计信息收集一次就够了,除非系统的硬件环境发生了变化,
    系统统计信息的收集方法请见“5.9系统统计信息”
    (7)建议要额外收集X$表的内部对象统计信息,但仅仅是在明确诊断出系统已有的性能问题是因为x$
    表的内部对象统计信息不准的情形下,对于其他情形就不要收集了。X$表的内部对象统计信息的收集方法和
    注意事项请见“5.1l内部对象统计信息”。


    2141
    适用于Oracle 11g及其以上的版本
    EXEC DBMS_STATS.GATHER_TABLE_STATS(
    OWNNAME=>'SCHEMA_NAME',
    TABNAME=>'TABLE NAME',
    ESTIMATE PERCENT=>DBMS STATS,AUTO_SAMPLE_SIZE,
    CASCADE=>TRUE,
    METROD_OPT=>'FOR ALL COLUMNS SIZE REPEAT'):

    2144
    锁住表的统计信息
    dbms_stats.lock_table_stats

    2148
    聚簇因子的大小对CBO判断是否走相关的索引至关重要

    20170426
    0951
    dbms_xplan.display_cursor(null,null,'ALLSTATS LAST')

    0959
    只要在sql中启用 hint,那么默认启用的cbo

    1012 hint格式
    hint 中第一个星号 (*)和加号(+)之间不能有空格
    hint zhong jiahao (+)和具体的hint内容之间可以有空格,也可以没有空格,通常都有
    hint中的具体内容可以使单个hint,也可以是多个hint的组合。如果是后者,则各个hint见至少需要一个空格来彼此分隔
    hint 必须紧跟 select、update、delete、insert、merge
    hint 中不能跟schema哦
    hint 如果后面 表指定了别名,全表扫描时  必须在hint中指定 别名

    1104
    _optimzer_ignore_hints 忽略sql中的  hint提示
    触发器执行该操作

    create or replace trigger ignore_hints_on_logon
    after logon on database
    begin
    execute immediate 'alter session set "_optimzer_ignore_hints"=true';
    end;
    /


    1120
    对于非分区索引而言,索引范围扫描或者索引全扫描都不可能并行执行

    1126
    /*+ use_hash(emp) */  hash连接的hint
    hash连接的被驱动表应该是数据量最多的那个表
    hash连接只使用于 等值连接查询

    1210
    cardinality(dept 100) 表示扫描表dept得到的结果集的 cardinality设为100

    1221
    hint  no_merge 禁用查询转换

    1227
    组合hint中各个hint间不要使用逗号“ ,” 来彼此分割(应该使用空格来彼此分隔)

    1235 all_rows
    让优化器启用cbo,而且在得到目标sql的执行计划时会选择那些吞吐量最佳的执行路径。吞吐量最佳   值资源消耗量最小(比如 i/o  cpu等硬件资源)

    1320
    INDEX_FFS 前提条件:select语句中所有的查询列都在目标索引中,即通过扫描目标索引就可以得到所有的查询咧而不用回表
    INDEX_JOIN 前提条件:select语句中所有的查询列都在目标表的多个目标索引中,即通过扫描这些索引就可以得到所有的查询列而不需要回表

    1327
    INDEX_FFS 执行计划
    INDEX_JOIN 执行计划

    1359
    sou> select /*+ rule */count(*)from tii ;

    Plan hash value:3110199320
    rd I operation
    0 I SBLECT STATEMENT
    SORT AGGREGATB
    I PX COORDINATOR
    SORT AGGREGATE
    PX BLOCR ITBRATOR I
    TABLE ACCESS FULLI T1
    一省略显示部分内容
    可以看出,上述SQL的执行计划已经从之前的串行全表扫摘表T1变为并行全表扫描花型,8
    新2ea”这表示上述SQL在解析时使用的是CBO,这也验证了之前的观点:如果日行
    为用于并行执行,就意味着其中的RULE Fmnt会失效,此此时Once会自动启用cBo

    1431
    PARALLEL hint的格式有如下4中:
    /*+ PARALLEL   */
    /*+ PARALLEL(AUTO) */  此处指定 auto,那么并行度 可能为1.因此不一定会用到 parallel
    /*+ PARALLEL(MANUAL) */
    /*+ PARALLEL(指定的并行度) */

    v$pq_slave


    1451
    NO_PARALLEL HINT

    1521
    driving_site(目标表)【强制操作在目标表执行】 原则 尽可能的减少本地节点和远程节点之间网络传输的数据量
    select /*+ driving_site(t)*/ col1,col2 from remote_tab@dblink_name

    1533
    直接路径加载数据一定要记得启用 parallel dml

    1536
    /*+ APPEND_VALUES */
     
     
    20170427

    0937
    检查绑定变量的传入值
    SQL> select
     snap_id,
     dbms_sqltune.extract_bind(bind_data,1).value_string bindi,
     dbms_sqltune.extract_bind(bind_data,2).value_string bind2,
     dbms_eqltune,extract_bind(bind_data,3).value_string bind3
    from dbs_hist_sqlstat
     where sql_id='&sql id
     order by snap_id;
    Enter value for sql_id:ay29xy01d36yb
    old 7:where sql_id='&sql_id'
    new 7:where sgl_id='ay29xy01d36yb'


    0945
    执行计划中 的
    Rows
    30M  此处30M 也就是 30*1000*1000  =3000万 哦

    0955
    取样默认 5%

    1108
    parallel hint  /*+ parallel_execution_demo_1 */
    serial   hint  /*+ serial_execution_demo_1 */

    1114
    强制启用dml操作的并行
    alter session force/enable  parallel dml;

    仅仅修改表的并行度和仅仅使用并行hint,不能真正并行执行dml。  记住!!!



    1127
    exec dbms_stats.gather_table_stats(ownname(用户名)=>'user_name',tabname(表名)=>'table_name',cascade=>true,estimate_percent=>100,degree(并行度)=>4  )

    1255
    kxfqcdty 就是列类型
    kxfqcplen 就是列的最大长度

    1324
    dba_tab_partitions  分区以 object的形式存在

    1355
    granule  粒度

    1403
    db file scattered read 数据文件散列读

    1409
    v$bh.dirty (y 脏块;n  非脏块)

    1412
    parallel 会产生一个 parallel query checkpoing
    “DBWR parallel query checkpoint buffers written”

    1423
    bbed

    1516
    要想使用并行 dml ,要么使用 alter session force parallel dml 要么使用 alter session enable parallel dml 和加了hint 的dml语句

    1922
    alter table table_name parallel n;
    alter index index_name parallel n;
     
    20170728
    procedure 中 执行 ddl 语句,例如:
    execute immediate 'alter session force parallel dml';



    commit/rollback;
    execute immediate 'alter session disable parallel dml';
    连接池中的连接  会被重复使用哦

    0915

    v$tracsaction的 列 used_ublk 表示用到的 undo_block的总数
                       used_urec 表示用到的 undo record的总数
                        cr_get 表示消耗的逻辑读(consistent gets)的总数
                        
    只需监控v$tracsaction的used_urec的值的递增情况就可以知道 sql的并行执行进度

    1018
    单键值索引:
    where col1 is not null; null 值 不会使用索引的   切记

    复合键值索引:
    where col1 is not null; null 值 会使用索引的  切记


    1031
    where col like '%aaa%'    这种情况不走索引

    1049

    在本书的“第2章Oracle里的执行计划”中我们已经提到,如果目标SQL的执行计划还在Shared Pool
    中,那就可以使用脚本display_cursor_9i.sql和存储过程printsql来得到其真实的执行计划和资源消耗,如果目
    标SOL的执行计划已经被age out出 Shared Pool了,那么我们可以执行DBMS_XPLAN.DISPLAY_AWR或者使用AWR SQL报告(获得AVR SQL报告的途径通常是手工执行脚本
    SORACLE_HOME/rdbms/admin/awrsqrpt.sql,适用于Oracle 10g及其以上的版本)和Statspack SQL报告(获得
    Statspack SQL报告的途径通常是手工执行脚本SORACLE_HOME/dbms/admin/sprepsql,适用于Oracle9i及其
    以上的版本)来得到其历史执行计划和资源消耗(DBMS_XPLAN DISPLAY_AWR仅能查看目标SQL的历史
    执行计划)。当我们得到了Top SQL的执行计划和资源消耗后,通常还会执行脚本sosibxt来获得上述Top SooL
    中相关对象的统计信息来辅助诊断,甚至还可能会对上述Top SL.使用10046/10053等事件,综合上述内容后
    你可以分析出此Top SOL的执行计划是否合理,是否存在性能问题了。display_cursor_9i.sql、printql和
    sosi.txt 都可以通过我网站上的Books专栏下载,网址为http /www dbsnake.net/books

    1106
    计算牟表的数据量
    sum(bytes)/1024/1024 dba_segments
    计算某个字段的 可选择率
    select count(col_name),count(distinct col_name)  from table_name


    --进程在等待什么
    select t.EVENT#,t.PROGRAM,t.SECONDS_IN_WAIT,t.STATE from v$session t where t.USERNAME='' and t.status='ACTIVE';

    --1129
    select t.TABLE_NAME,t.NUM_ROWS,t.BLOCKS,t.AVG_ROW_LEN,t.PARTITIONED,t.NUM_ROWS*t.AVG_ROW_LEN/1024/1024/0.9 est_M from dba_tables t
  • 相关阅读:
    Minimum Cost POJ
    SPFA费用流模板
    ISAP模板
    822D My pretty girl Noora
    822C Hacker, pack your bags!
    Dinic模板
    extjs最普通的grid
    springmvc配置首页的方式
    JSTL select和checkbox的用法
    请教<context:component-scan/>和<mvc:annotation-driven/>的区别20
  • 原文地址:https://www.cnblogs.com/iyoume2008/p/6721664.html
Copyright © 2011-2022 走看看