Chinaunix首页 | 论坛 | 博客
  • 博客访问: 12271
  • 博文数量: 10
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 110
  • 用 户 组: 普通用户
  • 注册时间: 2014-12-23 15:56
文章分类

全部博文(10)

文章存档

2014年(10)

我的朋友

分类: Oracle

2014-12-24 09:49:40


  1. DBMS_STATS包问世以后,ORACLE专家可通过一种简单的方式来为CBO收集统计数据。目前,已经不再推荐你使用老式的分析表和
  2. DBMS_UTILITY方法来生成CBO统计数据。那些古老的方式甚至有可能危及SQL的性能,
  3. 因为它们并非总是能够捕捉到有关表和索引的高质量信息。CBO使用对象统计,为所有SQL语句选择最佳的执行计划。
  4. DBMS_STATS能良好地估计统计数据(尤其是针对较大的分区表),并能获得更好的统计结果,最终制定出速度更快的SQL执行计划。

  5. GATHER_TABLE_STATS语法:

  6. DBMS_STATS.GATHER_TABLE_STATS
  7. (
  8.    OWNNAME VARCHAR2,
  9.    TABNAME VARCHAR2,
  10.    PARTNAME VARCHAR2 DEFAULT NULL,
  11.    ESTIMATE_PERCENT NUMBER DEFAULT TO_ESTIMATE_PERCENT_TYPE
  12.                                                 (GET_PARAM('ESTIMATE_PERCENT')),
  13.    BLOCK_SAMPLE BOOLEAN DEFAULT FALSE,
  14.    METHOD_OPT VARCHAR2 DEFAULT GET_PARAM('METHOD_OPT'),
  15.    DEGREE NUMBER DEFAULT TO_DEGREE_TYPE(GET_PARAM('DEGREE')),
  16.    GRANULARITY VARCHAR2 DEFAULT GET_PARAM('GRANULARITY'),
  17.    CASCADE BOOLEAN DEFAULT TO_CASCADE_TYPE(GET_PARAM('CASCADE')),
  18.    STATTAB VARCHAR2 DEFAULT NULL,
  19.    STATID VARCHAR2 DEFAULT NULL,
  20.    STATOWN VARCHAR2 DEFAULT NULL,
  21.    NO_INVALIDATE BOOLEAN DEFAULT TO_NO_INVALIDATE_TYPE (
  22.                                      GET_PARAM('NO_INVALIDATE')),
  23.    FORCE BOOLEAN DEFAULT FALSE
  24. );

  25.  

  26. 参数说明:

  27. OWNNAME: 要分析表的拥有者。
  28. TABNAME: 要分析的表名。
  29. PARTNAME: 分区的名字,只对分区表或分区索引有用。

  30. ESTIMATE_PERCENT: 采样行的百分比,取值范围[0.000001,100],使用常DBMS_STATS.AUTO_SAMPLE_SIZE让ORACLE决定适合的采样大小,
  31.                   这也是默认值,可以使用DBMS_STATS.SET_PARAM进行修改默认值。NULL可以让ORACLE采样全部数据
  32.                   
  33. BLOCK_SAMPLE: 是否采用随即块采样代替行随即行采样。

  34. METHOD_OPT: 决定HISTOGRAMS信息是怎样被统计的.METHOD_OPT的取值如下:
  35.             FOR ALL COLUMNS:统计所有列的HISTOGRAMS.
  36.             FOR ALL INDEXED COLUMNS:统计所有INDEXED列的HISTOGRAMS.
  37.             FOR ALL HIDDEN COLUMNS:统计你看不到列的HISTOGRAMS
  38.             FOR COLUMNS <LIST> SIZE <INTEGER> | REPEAT | AUTO |
  39.             INTEGER指的直方图的BUCKETS数量,取值范围为[1,254]
  40.             REPEAT上次统计过的HISTOGRAMS。
  41.             AUTO:ORACLE根据列数据的分布及相关列的访问量来决定收集直方图的列。
  42.             SKEWONLY:ORACLE 根据列的数据分布来决定哪些列收集直方图
  43.             。
  44. DEGREE: 并行度

  45. GRANULARITY: 收集统计信息的粒度。(只应用于分区表),值包括:
  46.              'ALL':搜集(SUBPARTITION,PARTITION,AND GLOBAL)统计信息。
  47.              'AUTO':基于分区的类型来决定粒度,默认值。
  48.              'DEFAULT':收集GLOBAL和PARTITION LEVEL的统计信息,等同与'GLOBAL AND PARTITION'
  49.              'GLOBAL':收集全局统计信息
  50.              'GLOBAL AND PARTITION':收集GLOBAL和PARTITION LEVEL统计信息。
  51.              'GPARTITION':收集PARTITION-LEVEL的统计信息。
  52.              'SUBPARTITION':收集SUBPARTITION-LEVEL统计信息
  53.              。
  54. CASCADE: 收集索引的统计信息。是收集索引的信息.默认为FALSE.

  55. STATTAB : 设置存储统计信息的表
  56. STATID : 表的ID
  57. STATOWN :表的OWNER

  58. NO_INVALIDATE: 若是设置为TRUE,则Oracle不会立马使 dependent Cursors失效,若设置为FALSE,Oracle则会立马使dependent Cursor失效.

  59. FORCE: 即使锁住也要收集表的统计信息。



  60. --关于GRANULARITY参数的一点说明

  61. --默认分区和全局均会收集统计信息


  62. create table t (id int,name varchar2(1000))
  63. partition by range(id)
  64. (
  65. partition p1 values less than (10000),
  66. partition p2 values less than (20000),
  67. partition p3 values less than (30000),
  68. partition pmax values less than (maxvalue)
  69. );

  70. exec dbms_stats.gather_table_stats('ADMIN','T');


  71. drop table t purge;


  72. --global_stats含义

  73. For partitioned tables, indicates whether statistics were collected for the table
  74. as a whole (YES) or were estimated from statistics on underlying partitions and subpartitions (NO)

  75. admin@ORCL> select num_rows,blocks,global_stats from user_tables where table_name = 'T';

  76.   NUM_ROWS BLOCKS GLO
  77. ---------- ---------- ---

  78.          0 0 YES


  79. admin@ORCL> select partition_name,num_rows,blocks,global_stats from user_tab_partitions;

  80. PARTITION_NAME NUM_ROWS BLOCKS GLO
  81. ------------------------------ ---------- ---------- ---

  82. P1 0 0 YES
  83. P2 0 0 YES
  84. P3 0 0 YES
  85. PMAX 0 0 YES

  86. insert into t select object_id,object_name from dba_objects
  87. commit;

  88. --只对partition层面做分析,根据以下的信息看出表级别的统计信息缺失的

  89. exec dbms_stats.gather_table_stats('ADMIN','T',granularity => 'partition');


  90. admin@ORCL> select num_rows,blocks,global_stats from user_tables where table_name = 'T';

  91.   NUM_ROWS BLOCKS GLO
  92. ---------- ---------- ---

  93.          0 0 YES

  94. admin@ORCL> select partition_name,num_rows,blocks,global_stats from user_tab_partitions;

  95. PARTITION_NAME NUM_ROWS BLOCKS GLO
  96. ------------------------------ ---------- ---------- ---

  97. P1 9708 43 YES
  98. P2 4557 20 YES
  99. P3 0 0 YES
  100. PMAX 1 5 YES


  101. admin@ORCL> select count(*) from T partition(P2);

  102.   COUNT(*)
  103. ----------

  104.       4557
  105.       
  106. --单个分区内的信息统计是准确的。

  107. admin@ORCL> select count(*) from T where ID < 10000;


  108. Execution Plan
  109. ----------------------------------------------------------

  110. Plan hash value: 2993254470

  111. ------------------------------------------------------------------------------------------------

  112. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
  113. ------------------------------------------------------------------------------------------------

  114. | 0 | SELECT STATEMENT | | 1 | 4 | 13 (0)| 00:00:01 | | |
  115. | 1 | SORT AGGREGATE | | 1 | 4 | | | | |
  116. | 2 | PARTITION RANGE SINGLE| | 9708 | 38832 | 13 (0)| 00:00:01 | 1 | 1 |
  117. | 3 | TABLE ACCESS FULL | T | 9708 | 38832 | 13 (0)| 00:00:01 | 1 | 1 |
  118. ------------------------------------------------------------------------------------------------

  119. --使用全局分区时,因为统计信息缺失,所以ROWS为1.


  120. admin@ORCL> select count(*) from T where ID < 30000;


  121. Execution Plan
  122. ----------------------------------------------------------

  123. Plan hash value: 2010034966

  124. --------------------------------------------------------------------------------------------------

  125. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
  126. --------------------------------------------------------------------------------------------------

  127. | 0 | SELECT STATEMENT | | 1 | 13 | 19 (0)| 00:00:01 | | |
  128. | 1 | SORT AGGREGATE | | 1 | 13 | | | | |
  129. | 2 | PARTITION RANGE ITERATOR| | 1 | 13 | 19 (0)| 00:00:01 | 1 | 3 |
  130. | 3 | TABLE ACCESS FULL | T | 1 | 13 | 19 (0)| 00:00:01 | 1 | 3 |
  131. --------------------------------------------------------------------------------------------------


  132. --跨分区的信息是不准确的。所以在收集统计信息时要注意同时收集全局和分区的统计信息

  133. admin@ORCL> select count(*) from T where ID < 10001;


  134. Execution Plan
  135. ----------------------------------------------------------

  136. Plan hash value: 2010034966

  137. --------------------------------------------------------------------------------------------------

  138. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
  139. --------------------------------------------------------------------------------------------------

  140. | 0 | SELECT STATEMENT | | 1 | 13 | 19 (0)| 00:00:01 | | |
  141. | 1 | SORT AGGREGATE | | 1 | 13 | | | | |
  142. | 2 | PARTITION RANGE ITERATOR| | 1 | 13 | 19 (0)| 00:00:01 | 1 | 2 |
  143. |* 3 | TABLE ACCESS FULL | T | 1 | 13 | 19 (0)| 00:00:01 | 1 | 2 |
  144. --------------------------------------------------------------------------------------------------



  145. 在11g时,当表上已经有全局统计信息时,单独对分区分析,不会更新全局信息。
  146. 当表上没有全局统计信息时,分析单独分区时,Oracle会自动把统计信息累积到全局之上。


  147. Oracle 的cardinality是不会为0的,至少是为1.

  148. 删除统计信息
  149. cascade_parts => false指不删除子分区的统计信息
  150. exec dbms_stats.delete_table_stats(user,'T',cascade_parts => false);

  151. --删除之后统计信息就没有了。

  152. admin@ORCL> select num_rows,blocks,global_stats from user_tables where table_name = 'T';

  153.   NUM_ROWS BLOCKS GLO
  154. ---------- ---------- ---

  155.                       NO

  156. --收集分区之上的统计信息,发现统计信息会合并到全局。也就不会出现上面的那种情况。

  157. admin@ORCL> exec dbms_stats.gather_table_stats('ADMIN','T',granularity => 'partition');

  158. PL/SQL procedure successfully completed.

  159. admin@ORCL> select num_rows,blocks,global_stats from user_tables where table_name = 'T';

  160.   NUM_ROWS BLOCKS GLO
  161. ---------- ---------- ---

  162.      14266 68 NO
  163.      
  164. admin@ORCL> select count(*) from t;

  165.   COUNT(*)
  166. ----------

  167.      14266


  168. 全局和全局信息
  169. 在Oracle 11g之后,有个增量统计信息的收集,在以前需要收集整个表,N个分区的统计信息数据,
  170. 才能够得到准确的全局统计信息,而Oracle 11g之后,增量收集分区信息来更新全局信息。
  171. 此方式适合特大的分区表进行收集统计信息。

  172. --告诉Oracle已增量的方式收集统计信息


  173. exec dbms_stats.set_table_prefs(user,'t','INCREMENTAL','TRUE');

  174. --Oracle 会以增量的方式收集统计信息,并更新全局信息。


  175. admin@ORCL> exec dbms_stats.gather_table_stats('ADMIN','T');

  176. PL/SQL procedure successfully completed.

  177. admin@ORCL> select num_rows,blocks,global_stats from user_tables where table_name = 'T';

  178.   NUM_ROWS BLOCKS GLO
  179. ---------- ---------- ---

  180.      14266 68 YES



  181. 分区和全局信息

  182. 如何设置这个参数
  183. 在一个很大的分区表(OLAP),全局分析代价是非常昂贵的。
  184. OLAP系统下,除了新加入的数据外,旧的数据基本上是没有变化的,全局分析很浪费资源。
  185. 对于很大分区表,将granulariy设置为partition(Oracle 10g)或者incremental(oracle 11g)是很有意义的。
  186. 对于不大的分区表,可以使用默认设置。

阅读(1097) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~