三,正文
1, 没有任何统计信息(包括表,索引,直方图等)
在ORACLE 10g中,RBO已经彻底的被抛弃了,取而代之的是CBO。我们知道CBO的基础就是统计信息,那么在10g中如果没有收集统计信息,CBO是怎么工作的呢?我们看下面的这个例子。
[@more@]Create table sunwg (Id number);
Create index ind_sunwg on sunwg(id);
Begin
For I in 1..100 loop
For j in 1..i loop
Insert into sunwg values (i);
End loop;
End loop;
Commit;
End;
这样我们就创建了一张有5050条记录的测试表。
例1, 不存在统计信息
SQL> select * from sunwg where id = 10;
已选择10行。
执行计划
----------------------------------------------------------
Plan hash value: 3109917279
---------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 10 | 130 | 1 (0)| 00:00:01 |* 1 | INDEX RANGE SCAN | IND_SUNWG | 10 | 130 | 1 (0)| 00:00:01 ---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("ID"=10)
Note
-----
- dynamic sampling used for this statement
统计信息
----------------------------------------------------------
9 recursive calls
0 db block gets
25 consistent gets
0 physical reads
124 redo size
478 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
10 rows processed
我们可以注意到Note中的说明dynamic sampling used for this statement,这表示在执行上面的SQL的时候,系统对表和索引进行了动态的取样。也就是说在执行这个SQL之前系统首先动态的收集表上和索引上的统计信息,然后利用这些统计信息通过CBO来找到合适的执行计划。这个统计的信息获得是需要很大的系统开销的,所以我们一定要把统计信息的收集放到一个重要的地位。那么这个收集后的统计信息会数据库保存起来供其他的SQL使用么?
如果这个统计信息被数据库保存起来的话,那么其他关于SUNWG表的查询也会利用到这些统计信息;反过来说,如果其他SQL没有使用统计信息的话,说明这些统计信息并没有被保存起来。
SQL> select * from sunwg where id = 50;
已选择50行。
执行计划
----------------------------------------------------------
Plan hash value: 3109917279
-----------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes|Cost (%CPU)| Time |
-----------------------------------------------------------------------| 0 | SELECT STATEMENT | | 50 | 650 | 1 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN| IND_SUNWG| 50 | 650 | 1 (0)| 00:00:01 -----------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("ID"=50)
Note
-----
- dynamic sampling used for this statement
统计信息
----------------------------------------------------------
7 recursive calls
0 db block gets
26 consistent gets
0 physical reads
0 redo size
1059 bytes sent via SQL*Net to client
418 bytes received via SQL*Net from client
5 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
50 rows processed
我们换了一个查询,可以看到这次仍然进行了动态的取样操作,由此可以证明这些统计信息并没有被ORACLE保存起来,对于没有统计信息的表每一个相关的查询都会进行动态的统计信息的收集。我也查询了大部分和统计信息相关的系统表,并没有发现这些统计信息,看来这些统计信息是和特定SQL关联的,并不会为其他的SQL使用。没有统计信息的后果是多么的可怕啊,本来3个逻辑读可以搞定的事情,却用了26个逻辑读才完成。
那么这个25个逻辑读到底读取了哪些内容呢,下面做个大概的测试。
SQL> analyze table sunwg compute statistics for table for all indexes;
表已分析。
SQL> select blocks,empty_blocks from user_tables;
BLOCKS EMPTY_BLOCKS
---------- ------------
13 3
SQL> select leaf_blocks from user_indexes;
LEAF_BLOCKS
-----------
9
13 + 9 + 3 = 25
虽然可能不那么准确,也可以看得出来在进行动态统计信息收集的时候会对表和表上索引进行统计,浪费大量的IO,这种浪费并不是仅仅出现一次,在以后的每次查询的时候会存在的,直到你开始收集统计信息为止。来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/8394333/viewspace-1000431/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/8394333/viewspace-1000431/