有两张表格超过 2000万的记录。数据库版本为Oracle 11.2.0.3.13标准版
SQL> select count(*) from atsd_tra_trade_print;
COUNT(*)
----------
20000000
SQL> select count(*) from atsd_mob_allocation_pos;
COUNT(*)
----------
20551780
我们对表运行以下查询。 查询结构类似。查询用于分页。 两个查询的排序列都已编入索引,并且不包含任何NULL值。查询和相应的autotrace输出/计划如下所示。
索引 INDX_ATTP_6 在ATSD_TRA_TRADE_PRINT( TRANSACT_TIME )上创建
索引 INDX_AMAP_6 是在ATSD_MOB_SETTLEMENT_POS上创建的( DATE_TIME )
索引的基数如下
INDX_ATTP_6 - 5972
INDX_AMAP_6 - 5974
上述两列的数据类型为 varchar2 。
在刷新buffer_cache 后,两个查询都运行。还收集了模式统计数据。
SELECT * FROM ( SELECT T2.*, ROWNUM AS RN FROM (
SELECT *
FROM ATSDN_TRA_TRADE_PRINT T
WHERE LATEST = 1
ORDER BY TRANSACT_TIME) T2)
WHERE RN > 0 and ROWNUM <= 28;
输出:
28 rows selected.
Elapsed: 00:00:00.16
Execution Plan
----------------------------------------------------------
Plan hash value: 3823692003
------------------------------------------------------------------------- -------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------- -------------------------------
| 0 | SELECT STATEMENT | | 28 | 60060 | 8 (0)| 00:00:01 |
|* 1 | COUNT STOPKEY | | | | | |
|* 2 | VIEW | | 28 | 60060 | 8 (0)| 00:00:01 |
| 3 | COUNT | | | | | |
| 4 | VIEW | | 28 | 59696 | 8 (0)| 00:00:01 |
|* 5 | TABLE ACCESS BY INDEX ROWID| ATSD_TRA_TRADE_PRINT | 7488K| 3234M| 8 (0)| 00:00:01 |
| 6 | INDEX FULL SCAN | INDX_ATTP_6 | 57 | | 3 (0)| 00:00:01 |
------------------------------------------------------------------------- -------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(ROWNUM<=28)
2 - filter("RN">0)
5 - filter("LATEST"=1)
Statistics
----------------------------------------------------------
571 recursive calls
0 db block gets
948 consistent gets
49 physical reads
0 redo size
18586 bytes sent via SQL*Net to client
535 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
29 sorts (memory)
0 sorts (disk)
28 rows processed
上述查询按预期快速执行。但是对另一个表的查询会导致执行时间过长。我能看到的唯一观察是有大量的物理读取。两个查询执行计划看起来都很相似。
SELECT * FROM ( SELECT T2.*, ROWNUM as RN FROM (
SELECT *
FROM ATSD_MOB_ALLOCATION_POS AL
WHERE LATEST = 1
ORDER BY DATE_TIME) T2)
WHERE RN > 0 and ROWNUM <= 28;
输出:
28 rows selected.
Elapsed: 00:01:52.28
Execution Plan
----------------------------------------------------------
Plan hash value: 884170602
------------------------------------------------------------------------- ----------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------- ----------------------------------
| 0 | SELECT STATEMENT | | 28 | 38892 | 7 (0)| 00:00:01 |
|* 1 | COUNT STOPKEY | | | | | |
|* 2 | VIEW | | 28 | 38892 | 7 (0)| 00:00:01 |
| 3 | COUNT | | | | | |
| 4 | VIEW | | 28 | 38528 | 7 (0)| 00:00:01 |
|* 5 | TABLE ACCESS BY INDEX ROWID| ATSD_MOB_ALLOCATION_POS | 14M| 5863M| 7 (0)| 00:00:01 |
| 6 | INDEX FULL SCAN | INDX_AMAP_6 | 39 | | 4 (0)| 00:00:01 |
------------------------------------------------------------------------- ----------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(ROWNUM<=28)
2 - filter("RN">0)
5 - filter("LATEST"=1)
Statistics
----------------------------------------------------------
281 recursive calls
0 db block gets
335395 consistent gets
332763 physical reads
116 redo size
13582 bytes sent via SQL*Net to client
535 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
17 sorts (memory)
0 sorts (disk)
28 rows processed
有人可以告诉我为什么会这样。在此先感谢... :)
答案 0 :(得分:0)
问题在于索引结构......当它以asc方式遍历索引INDX_AMAP_6时,它必须在满足过滤条件的行之前读取500万条记录&#34; LATEST = 1&#34 ;。排序列和文件管理器列上的复合索引解决了这个问题。
在atsd_mob_allocation_pos上创建索引AMAP_TEST1(最新,date_time);