表统计信息的收集时间可以从user_table的analylize_time中得知,但是统计信息是否准确,还是不好判断,上课中郭老师提出了采用dbms_xplan.display_cursor查看收集的信息可以帮助我们判断统计信息是否陈旧。
如下是具体的操作方式:
SQL> set linesize 1000
SQL> Set pagesize 100
SQL> drop table test1 purge;
表已删除。
SQL> drop table test2 purge;
表已删除。
SQL> create table test1 as select * from dba_objects where rownum <=100;
表已创建。
SQL> create table test2 as select * from dba_objects where rownum <=1000;
表已创建。
-- statistics_level有三个值,basic,typical,all。如果为basic则关闭所有性能数据的收集;如果是typical,除了plan_executetion_statistics和OS statistics不能收集,其他都能收集;all即都收集。
--statistics_level设为all,收集所有信息
SQL> alter session set statistics_level=all;
会话已更改。
--采用hint让其不要动态收集统计信息(一般统计信息没收集过的表在执行sql时会动态收集)
SQL> select /*+Dynamic_sampling(0)*/count(*)
2 from test1 t1, test2 t2
3 where t1.object_id = t2.object_id;
COUNT(*)
----------
100
--查看最新收集的信息(dbms_xplan.display_cursor)
SQL> SELECT * FROM table(dbms_xplan.display_cursor(NULL,NULL,'allstats last'));
PLAN_TABLE_OUTPUT
---------------------------------------------------------
SQL_ID 55ga693yggjkd, child number 0
-------------------------------------
select /*+Dynamic_sampling(0)*/count(*) from test1 t1, test2 t2
where t1.object_id = t2.object_id
Plan hash value: 2544416891
---------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | OMem | 1Mem | Used-Mem |
---------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.06 | 20 | 15 | | | |
| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.06 | 20 | 15 | | | |
|* 2 | HASH JOIN | | 1 | 1307 | 100 |00:00:00.06 | 20 | 15 | 1517K | 1517K | 1260K (0)|
| 3 | TABLE ACCESS FULL| TEST1 | 1 | 409 | 100 |00:00:00.06 | 4 | 2 | | | |
| 4 | TABLE ACCESS FULL| TEST2 | 1 | 1307 | 1000 |00:00:00.01 | 16 | 13 | | | |
---------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("T1"."OBJECT_ID"="T2"."OBJECT_ID")
已选择22行。
如上信息可以看到,表信息在没收集的情况下,e-rows(评估的行数)和a-rows(实际行数)存在很大的差距。
--对表进行手动收集统计信息
SQL> exec dbms_stats.gather_table_stats(user,'test1');
PL/SQL 过程已成功完成。
SQL> exec dbms_stats.gather_table_stats(user,'test2');
PL/SQL 过程已成功完成。
--再次执行该语句并查看其收集的信息
SQL> SELECT count(*)
2 from test1 t1, test2 t2
3 where t1.object_id = t2.object_id;
COUNT(*)
----------
100
SQL> SELECT * FROM table(dbms_xplan.display_cursor(NULL,NULL,'allstats last'));
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------------
SQL_ID dt23w69fu80v4, child number 0
------------------------------------------------------------------------------------------
SELECT count(*) from test1 t1, test2 t2 where t1.object_id =
t2.object_id
Plan hash value: 2544416891
------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |
------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 20 | | | |
| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.01 | 20 | | | |
|* 2 | HASH JOIN | | 1 | 100 | 100 |00:00:00.01 | 20 | 1517K| 1517K| 1463K (0)|
| 3 | TABLE ACCESS FULL| TEST1 | 1 | 100 | 100 |00:00:00.01 | 4 | | | |
| 4 | TABLE ACCESS FULL| TEST2 | 1 | 1000 | 1000 |00:00:00.01 | 16 | | | |
------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("T1"."OBJECT_ID"="T2"."OBJECT_ID")
已选择22行。
表统计信息准确后,发现评估的行数与实际的行数完全一致。
附:查询出的统计信息标题含义
Starts:该sql执行的次数。
E-Rows:执行计划预计的行数。
A-Rows:实际返回的行数。
A-Time:每一步实际执行的时间(HH:MM:SS.FF),根据这一行可以知道该sql耗时在哪个地方。
Buffers:每一步实际执行的逻辑读或一致性读。
Reads:物理读。
OMem、1Mem:执行所需的内存评估值,OMem为最优执行模式所需内存的评估值,1Mem为one-pass模式所需内存的评估值。
O/1/M :最优/one-pass/multipass执行的次数。
Used-Mem:耗的内存。
注:如果执行中都没有涉及到的项,则在收集中就不会出现该项,如上述第一次执行的sql在收集的信息中有reads,但是表收集统计信息后再次执行因为不存在物理读,所以在第二个收集的信息中就没有reads这一项。