• Oracle表分析


    Oracle表分析


    当表没有做分析的时候,Oracle 会使用动态采样来收集统计信息。 获取准确的段对象(表,表分区,索引等)的分析数据,是CBO存在的基石,CBO的机制就是收集尽可能多的对象信息和系统信息,通过对这些信息进行计算,分析,评估,最终得出一个成本最低的执行计划。所以对于CBO,数据段的分析就非常重要。

    分析SQL

    analyze table tablename compute statistics
    等同于
    analyze table tablename compute statistics for table for all indexes for all columns
    for table的统计信息存在于视图:user_tables 、all_tables、dba_tables
    for allindexes的统计信息存在于视图: user_indexes 、all_indexes、dba_indexes
    for allcolumns的统计信息存在于试图:user_tab_columns、all_tab_columns、dba_tab_columns

    或者

    SQL> exec dbms_stats.gather_table_stats(user,'xiaogongjiang');

    生成的统计信息会存在于user_tables这个视图,查看一下

    select * from user_tables where table_name=table_name;

    观察一下NUM_ROWS,BLOCKS,AVG_SPACE,AVG_ROW_LEN几列你就会明白,这就是变化。

    删除SQL
    analyze table tablename delete statistics 会删除所有的statistics
    作用
    Oracle分析表的作用:为了使基于CBO的执行计划更加准确

    数据准备

    Connected to Oracle Database 11g Enterprise Edition Release 11.2.0.4.0
    Connected as xx@xgj

    SQL> create table xiaogongjiang as select a.OBJECT_ID ,a.OBJECT_NAME from dba_objects a ;--创建表

    Table created

    SQL> select count(1) from xiaogongjiang;

    COUNT(1)
    ----------
    35183

    SQL> create index idx_object_id on xiaogongjiang(object_id);--在object_id建立索引

    Index created

    SQL>


    分析前的数据及执行计划

    SQL> select num_rows, avg_row_len, blocks, last_analyzed from user_tables where table_name = 'XIAOGONGJIANG';--表的信息

    NUM_ROWS AVG_ROW_LEN BLOCKS LAST_ANALYZED
    ---------- ----------- ---------- -------------


    SQL> select blevel,leaf_blocks,distinct_keys,last_analyzed from user_indexes where table_name='XIAOGONGJIANG';--索引信息

    BLEVEL LEAF_BLOCKS DISTINCT_KEYS LAST_ANALYZED
    ---------- ----------- ------------- -------------

    从查询结果看出,表的行数,行长,占用的数据块数及最后的分析时间都是空。 索引的相关信息也没有,说明这个表和说因都没有被分析,如果此时有一条SQL 对表做查询,CBO 由于无法获取这些信息,很可能生成错误的执行计划。
    查询执行计划
    --执行sql,以便存到shared pool中
    SQL>select /*+dynamic_sampling(xiaogongjiang 0) */ * from XIAOGONGJIANG where object_id>30;
    .....省略输出

    -- 查询出上个执行脚本对应的sql_id:5h16pnkvs0r5z
    SQL>select * from v$sql a where a.SQL_TEXT like '%select /*+dynamic_sampling(xiaogongjiang 0) */ * from XIAOGONGJIANG where object_id>30%';
    .....省略输出

    --使用dbms_xplan.display_cursor查看sql真正的执行计划
    SQL>select * from table(dbms_xplan.display_cursor('5h16pnkvs0r5z'));

    导出html,查看如下

     

     

     

    在Oracle 10g以后,如果一个表没有做分析,数据库将自动对它做动态采样分析,

    所以这里采用hint的方式将动态采样的级别设置为0,即不使用动态采样。

    分析后的数据及执行计划
    第一种方式
    SQL> analyze table xiaogongjiang compute statistics ;

    Table analyzed

    第二种方式(推荐)
    SQL> exec dbms_stats.gather_table_stats(user,'xiaogongjiang');

    PL/SQL procedure successfully completed

    SQL> 第一个参数为用户,第二个参数为表

    通过DBMS_STATS包来分析,从9i 开始,Oracle 推荐使用DBMS_STATS包对表进行分析操作,因为DBMS_STATS 提供了更多的功能,以及灵活的操作方式。

    SQL> select num_rows, avg_row_len, blocks, last_analyzed from user_tables where table_name = 'XIAOGONGJIANG';

    NUM_ROWS AVG_ROW_LEN BLOCKS LAST_ANALYZED
    ---------- ----------- ---------- -------------
    35183 27 152 2016-12-02 0:


    SQL> select blevel,leaf_blocks,distinct_keys,last_analyzed from user_indexes where table_name='XIAOGONGJIANG';

    BLEVEL LEAF_BLOCKS DISTINCT_KEYS LAST_ANALYZED
    ---------- ----------- ------------- -------------
    1 77 35180 2016-12-02 0:

    从上面的结果,可以看出DBMS_STATS.gather_table_stats已经对表和索引都做了分析。 现在我们在来看一下执行计划。

    SQL>select * from xiaogongjiang where object_id>30;

    SQL>select * from v$sql a where a.SQL_TEXT like '%select * from xiaogongjiang where object_id>30%';

    SQL>select * from table(dbms_xplan.display_cursor('gzspgs4btcpuf'));

    从这个计划,我们看出CBO 估算出的结果是35153条记录,与实际的35183很近。 此时选择全表扫描更优。 通过这个例子,我们也看出了分析对执行计划的重要性。

     

     由于Oracle的优化器是CBO,所以对象的统计数据对执行计划的生成至关重要!
     
     作用:DBMS_STATS.GATHER_TABLE_STATS统计表,列,索引的统计信息(默认参数下是对表进行直方图信息收集,包含该表的自身-表的行数、数据块数、行长等信息;列的分析--列值的重复数、列上的空值、数据在列上的分布情况;索引的分析-索引页块的数量、索引的深度、索引聚合因子).

     

    DBMS_STATS.GATHER_TABLE_STATS的语法如下:

    DBMS_STATS.GATHER_TABLE_STATS (   ownname          VARCHAR2,     tabname          VARCHAR2,     partname         VARCHAR2,   estimate_percent NUMBER,     block_sample     BOOLEAN,   method_opt       VARCHAR2,   degree           NUMBER,   granularity      VARCHAR2,     cascade          BOOLEAN,   stattab          VARCHAR2,     statid           VARCHAR2,   statown          VARCHAR2,   no_invalidate    BOOLEAN,   force            BOOLEAN);

    参数说明:

    ownname:要分析表的拥有者

    tabname:要分析的表名.

    partname:分区的名字,只对分区表或分区索引有用.

    estimate_percent:采样行的百分比,取值范围[0.000001,100],null为全部分析,不采样. 常量:DBMS_STATS.AUTO_SAMPLE_SIZE是默认值,由oracle决定最佳取采样值.

    block_sapmple:是否用块采样代替行采样.

    method_opt:决定histograms信息是怎样被统计的.method_opt的取值如下(默认值为FOR ALL COLUMNS SIZE AUTO):

    for all columns:统计所有列的histograms.

    for all indexed columns:统计所有indexed列的histograms.

    for all hidden columns:统计你看不到列的histograms

    for columns <list> SIZE <N> | REPEAT | AUTO | SKEWONLY:统计指定列的histograms.N的取值范围[1,254]; REPEAT上次统计过的histograms;AUTO由oracle决定N的大小;SKEWONLY multiple end-points with the same value which is what we define by "there is skew in thedata

    degree:决定并行度.默认值为null.

    granularity:Granularity of statistics to collect ,only pertinent if the table is partitioned.

    cascade:是收集索引的信息.默认为FALSE.

    stattab:指定要存储统计信息的表,statid如果多个表的统计信息存储在同一个stattab中用于进行区分.statown存储统计信息表的拥有者.以上三个参数若不指定,统计信息会直接更新到数据字典.

    no_invalidate: Does not invalidate the dependent cursors if set to TRUE. The procedure invalidates the dependent cursors immediately if set to FALSE.

    force:即使表锁住了也收集统计信息.

    例子:

    execute dbms_stats.gather_table_stats(ownname => 'owner',tabname => 'table_name' ,estimate_percent => null ,method_opt => 'for all indexed columns' ,cascade => true);

    ------------------------------------------------------------------------------------------------------------------------

    自从Oracle8.1.5引入dbms_stats包,Experts们便推荐使用dbms_stats取代analyze。 理由如下
    dbms_stats可以并行分析
    dbms_stats有自动分析的功能(alter table monitor )
    analyze 分析统计信息的不准确some times
    1,2好理解,且第2点实际上在VLDB中是最吸引人的;3以前比较模糊,看了metalink236935.1 解释,analyze在分析Partition表的时候,有时候会计算出不准确的Global statistics .
    原因是,dbms_stats会实在的去分析表全局统计信息(当指定参数);而analyze是将表分区(局部)的statistics 汇总计算成表全局statistics ,可能导致误差。
    如果想分析整个用户或数据库,还可以采用工具包,可以并行分析
    Dbms_utility(8i以前的工具包)
    Dbms_stats(8i以后提供的工具包)

    dbms_stats.gather_schema_stats(User,estimate_percent=>100,cascade=> TRUE);
    dbms_stats.gather_table_stats(User,TableName,degree => 4,cascade => true);

    如何使用dbms_stats分析统计信息?
    --创建统计信息历史保留表 

    sql> exec dbms_stats.create_stat_table(ownname => 'scott',stattab => 'stat_table') ; 


    --导出整个scheme的统计信息 

    sql> exec dbms_stats.export_schema_stats(ownname => 'scott',stattab => 'stat_table') ; 


    --分析scheme

    Exec dbms_stats.gather_schema_stats( 
    ownname => 'scott', 
    options => 'GATHER AUTO', 
    estimate_percent => dbms_stats.auto_sample_size, 
    method_opt => 'for all indexed columns ', 
    degree => 6 ) 


    --分析表

    sql> exec dbms_stats.gather_table_stats(ownname => 'scott',tabname => 'work_list',estimate_percent => 10,method_opt=> 'for all indexed columns') ; 


    --分析索引

    SQL> exec dbms_stats.gather_index_stats(ownname => 'crm2',indname => 'IDX_ADM_PERMISSION_PID_MID',estimate_percent => '10',degree => '4') ;


    --如果发现执行计划走错,删除表的统计信息

    SQL>dbms_stats.delete_table_stats(ownname => 'scott',tabname => 'work_list') ;


    --导入表的历史统计信息

    sql> exec dbms_stats.import_table_stats(ownname => 'scott',tabname => 'work_list',stattab => 'stat_table') ; 


    --如果进行分析后,大部分表的执行计划都走错,需要导回整个scheme的统计信息

    sql> exec dbms_stats.import_schema_stats(ownname => 'scott',stattab => 'stat_table');


    --导入索引的统计信息

    SQL> exec dbms_stats.import_index_stats(ownname => 'crm2',indname => 'IDX_ADM_PERMISSION_PID_MID',stattab => 'stat_table') 


    --检查是否导入成功

    SQL> select table_name,num_rows,a.blocks,a.last_analyzed from all_tables a where a.table_name='WORK_LIST'; 


    分析数据库(包括所有的用户对象和系统对象):gather_database_stats 
    分析用户所有的对象(包括表、索引、簇):gather_schema_stats
    分析表:gather_table_stats
    分析索引:gather_index_stats 
    删除数据库统计信息:delete_database_stats
    删除用户方案统计信息:delete_schema_stats
    删除表统计信息:delete_table_stats 
    删除索引统计信息:delete_index_stats
    删除列统计信息:delete_column_stats 
    设置表统计信息:set_table_stats
    设置索引统计信息:set_index_stats
    设置列统计信息:set_column_stats 

    可以查看表 DBA_TABLES来查看表是否与被分析过,如:

    SELECT TABLE_NAME, LAST_ANALYZED FROM DBA_TABLES

     

    这是对命令与工具包的一些总结
    1、对于分区表,建议使用DBMS_STATS,而不是使用Analyze语句。
    a) 可以并行进行,对多个用户,多个Table
    b) 可以得到整个分区表的数据和单个分区的数据。
    c) 可以在不同级别上Compute Statistics:单个分区,子分区,全表,所有分区
    d) 可以倒出统计信息
    e) 可以用户自动收集统计信息
    2、DBMS_STATS的缺点
    a) 不能Validate Structure
    b) 不能收集CHAINED ROWS, 不能收集CLUSTER TABLE的信息,这两个仍旧需要使用Analyze语句。
    c) DBMS_STATS 默认不对索引进行Analyze,因为默认Cascade是False,需要手工指定为True
    3、对于oracle 9里面的External Table,Analyze不能使用,只能使用DBMS_STATS来收集信息。

     

    https://blog.csdn.net/yangshangwei/article/details/53428259

    https://www.cnblogs.com/wbzhao/archive/2012/04/05/2433616.html

  • 相关阅读:
    发现个atan2的正确使用方式
    Forward+ Shading架构
    fatal: unable to connect to gitee.com: gitee.com[0: 180.97.125.228]: errno=Unknown error 解决方案
    HDFS HA(高可用性)集群规划
    如何使用RTP引擎对语音编码进行转码
    关于 Angular 应用 tsconfig.json 中的 target 属性
    浅谈 Orbeon form builder 的权限控制
    关于 Angular 应用 tsconfig.json 中的 lib 属性
    orbeon form 通过 url 的方式同第三方应用集成的开发明细
    orbeon form 的配置介绍
  • 原文地址:https://www.cnblogs.com/pugang/p/13539348.html
Copyright © 2020-2023  润新知