sql – 在创建索引并使用dbms_stats计算之后,查询执行速度较慢
|
我有一个150万行的桌子.我运行一个查询,它在列中获取具有非重复值的记录.我正在观察一个行为,其中创建索引后,查询的性能下降.我还使用了百分之百估计百分比的dbms_stats(计算模式)
SQL> desc tab3; Name Null? Type ---------------------------------------------- COL1 NUMBER(38) COL2 VARCHAR2(100) COL3 VARCHAR2(36) COL4 VARCHAR2(36) COL5 VARCHAR2(4000) COL6 VARCHAR2(4000) MEASURE_0 VARCHAR2(4000) MEASURE_1 VARCHAR2(4000) MEASURE_2 VARCHAR2(4000) MEASURE_3 VARCHAR2(4000) MEASURE_4 VARCHAR2(4000) MEASURE_5 VARCHAR2(4000) MEASURE_6 VARCHAR2(4000) MEASURE_7 VARCHAR2(4000) MEASURE_8 VARCHAR2(4000) MEASURE_9 VARCHAR2(4000) 列measure_0具有40万个唯一值. SQL> select count(*) from (select measure_0 from tab3 group by measure_0 having count(*) = 1) abc;
COUNT(*)
----------
403664
以下是执行计划的查询,请注意,表上没有索引. SQL> set autotrace traceonly;
SQL> SELECT * FROM (
2 SELECT
3 (ROWNUM -1) AS COL1,4 ft.COL1 AS OLD_COL1,5 ft.COL2,6 ft.COL3,7 ft.COL4,8 ft.COL5,9 ft.COL6,10 ft.MEASURE_0,11 ft.MEASURE_1,12 ft.MEASURE_2,13 ft.MEASURE_3,14 ft.MEASURE_4,15 ft.MEASURE_5,16 ft.MEASURE_6,17 ft.MEASURE_7,18 ft.MEASURE_8,19 ft.MEASURE_9
20 FROM tab3 ft
21 WHERE MEASURE_0 IN
22 (
23 SELECT MEASURE_0
24 FROM tab3
25 GROUP BY MEASURE_0
26 HAVING COUNT(*) = 1
27 )
28 ) ABC WHERE COL1 >= 0 AND COL1 <=449;
450 rows selected.
Elapsed: 00:00:01.90
Execution Plan
----------------------------------------------------------
Plan hash value: 3115757351
------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1243 | 28M| 717K (1)| 02:23:29 |
|* 1 | VIEW | | 1243 | 28M| 717K (1)| 02:23:29 |
| 2 | COUNT | | | | | |
|* 3 | HASH JOIN | | 1243 | 30M| 717K (1)| 02:23:29 |
| 4 | VIEW | VW_NSO_1 | 1686K| 3219M| 6274 (2)| 00:01:16 |
|* 5 | FILTER | | | | | |
| 6 | HASH GROUP BY | | 1 | 3219M| 6274 (2)| 00:01:16 |
| 7 | TABLE ACCESS FULL| TAB3 | 1686K| 3219M| 6196 (1)| 00:01:15 |
| 8 | TABLE ACCESS FULL | TAB3 | 1686K| 37G| 6211 (1)| 00:01:15 |
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("COL1">=0 AND "COL1"<=449)
3 - access("MEASURE_0"="MEASURE_0")
5 - filter(COUNT(*)=1)
Note
-----
- dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
354 recursive calls
0 db block gets
46518 consistent gets
45122 physical reads
0 redo size
43972 bytes sent via SQL*Net to client
715 bytes received via SQL*Net from client
31 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
450 rows processed
查询占用1.90秒.如果我再次运行查询,则需要1.66秒.为什么在第一次运行中需要更多时间? 为了加快速度,我在查询中使用的两列中创建了索引. SQL> create index ind_tab3_orgid on tab3(COL1); Index created. Elapsed: 00:00:01.68 SQL> create index ind_tab3_msr_0 on tab3(measure_0); Index created. Elapsed: 00:00:01.83 当我第一次发出这个查询之后,花了21秒才回来.而后续的运行则是2.9秒.为什么oracle在第一次运行中花费了这么多时间,是暖身还是什么东西呢?挡住了我! 这是计划,当它需要2.9秒 – 450 rows selected.
Elapsed: 00:00:02.92
Execution Plan
----------------------------------------------------------
Plan hash value: 240271480
-------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1243 | 28M| 711K (1)| 02:22:15 |
|* 1 | VIEW | | 1243 | 28M| 711K (1)| 02:22:15 |
| 2 | COUNT | | | | | |
| 3 | NESTED LOOPS | | | | | |
| 4 | NESTED LOOPS | | 1243 | 30M| 711K (1)| 02:22:15 |
| 5 | VIEW | VW_NSO_1 | 1686K| 3219M| 6274 (2)| 00:01:16 |
|* 6 | FILTER | | | | | |
| 7 | HASH GROUP BY | | 1 | 3219M| 6274 (2)| 00:01:16 |
| 8 | TABLE ACCESS FULL | TAB3 | 1686K| 3219M| 6196 (1)| 00:01:15 |
|* 9 | INDEX RANGE SCAN | IND_TAB3_MSR_0 | 1243 | | 2 (0)| 00:00:01 |
| 10 | TABLE ACCESS BY INDEX ROWID| TAB3 | 1243 | 28M| 44 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("COL1">=0 AND "COL1"<=449)
6 - filter(COUNT(*)=1)
9 - access("MEASURE_0"="MEASURE_0")
Note
-----
- dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
660054 consistent gets
22561 physical reads
0 redo size
44358 bytes sent via SQL*Net to client
715 bytes received via SQL*Net from client
31 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
450 rows processed
我期待的时间要低于桌子未被索引的时间.为什么表的索引版本比非索引版本需要更多的时间来获取结果?如果我没有错,那是正在占用时间的TABLE ACCESS BY INDEX ROWID.我可以强制执行oracle来使用TABLE ACCESS FULL吗? 然后我收集了表上的统计数据,以便CBO通过计算选项来改进计划.所以现在的统计数字是准确的. SQL> EXECUTE dbms_stats.gather_table_stats (ownname=>'EQUBE67DP',tabname=>'TAB3',estimate_percent=>null,cascade=>true); PL/SQL procedure successfully completed. Elapsed: 00:01:02.47 SQL> set autotrace off; SQL> select COLUMN_NAME,NUM_DISTINCT,SAMPLE_SIZE,HISTOGRAM,LAST_ANALYZED from dba_tab_cols where table_name = 'TAB3' ; COLUMN_NAME NUM_DISTINCT SAMPLE_SIZE HISTOGRAM LAST_ANALYZED ------------------------------ ------------ ----------- --------------- --------- COL1 1502257 1502257 NONE 27-JUN-12 COL2 0 NONE 27-JUN-12 COL3 1 1502257 NONE 27-JUN-12 COL4 0 NONE 27-JUN-12 COL5 1502257 1502257 NONE 27-JUN-12 COL6 1502257 1502257 NONE 27-JUN-12 MEASURE_0 405609 1502257 HEIGHT BALANCED 27-JUN-12 MEASURE_1 128570 1502257 NONE 27-JUN-12 MEASURE_2 1502257 1502257 NONE 27-JUN-12 MEASURE_3 185657 1502257 NONE 27-JUN-12 MEASURE_4 901 1502257 NONE 27-JUN-12 MEASURE_5 17 1502257 NONE 27-JUN-12 MEASURE_6 2202 1502257 NONE 27-JUN-12 MEASURE_7 2193 1502257 NONE 27-JUN-12 MEASURE_8 21 1502257 NONE 27-JUN-12 MEASURE_9 27263 1502257 NONE 27-JUN-12 (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
