联系:QQ(5163721)
标题:让“select min(xxx),max(xxx) from xxx”走索引
作者:Lunar©版权所有[文章允许转载,但必须以链接方式注明源地址,否则追究法律责任.]
首先,做一个测试表:
[oracle@lunar /]$ ss SQL*Plus: Release 11.2.0.3.0 Production on Sat Jun 7 21:29:52 2014 Copyright (c) 1982, 2011, Oracle. All rights reserved. Welcome Lunar's oracle world! Love you , baby ! Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production With the Partitioning and Real Application Testing options SYS@lunar>conn lunar/lunar Welcome Lunar's oracle world! Love you , baby ! Connected. LUNAR@lunar>create table lunar as select * from dba_extents; Table created. Elapsed: 00:00:04.61
在extent_id列上创建非唯一索引:
LUNAR@lunar>create index idx_lunar_extent_id on lunar(extent_id) ; Index created. Elapsed: 00:00:00.02 LUNAR@lunar>EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME => 'LUNAR',TABNAME => 'LUNAR',DEGREE => 5, 2 CASCADE => TRUE,ESTIMATE_PERCENT => DBMS_STATS.AUTO_SAMPLE_SIZE); PL/SQL procedure successfully completed. Elapsed: 00:00:01.45
下面的语句没有走索引:
LUNAR@lunar>select min(extent_id),max(extent_id) from lunar;
MIN(EXTENT_ID) MAX(EXTENT_ID)
-------------- --------------
0 61
Elapsed: 00:00:00.01
Execution Plan
----------------------------------------------------------
Plan hash value: 291688323
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 3 | 16 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 3 | | |
| 2 | TABLE ACCESS FULL| LUNAR | 5223 | 15669 | 16 (0)| 00:00:01 |
----------------------------------------------------------------------------
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
51 consistent gets
0 physical reads
0 redo size
610 bytes sent via SQL*Net to client
524 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
LUNAR@lunar>
手工指定IDX_LUNAR_EXTENT_ID时,也不走索引:
LUNAR@lunar>select /*+ index(lunar IDX_LUNAR_EXTENT_ID) */ min(extent_id),max(extent_id) from lunar;
MIN(EXTENT_ID) MAX(EXTENT_ID)
-------------- --------------
0 61
Elapsed: 00:00:00.01
Execution Plan
----------------------------------------------------------
Plan hash value: 291688323
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 3 | 16 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 3 | | |
| 2 | TABLE ACCESS FULL| LUNAR | 5223 | 15669 | 16 (0)| 00:00:01 |
----------------------------------------------------------------------------
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
50 consistent gets
0 physical reads
0 redo size
610 bytes sent via SQL*Net to client
524 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
LUNAR@lunar>
指定该列为非空时,可以走索引(Oracle的索引不保存空值):
LUNAR@lunar>alter table lunar modify extent_id not null; Table altered. Elapsed: 00:00:00.24 LUNAR@lunar>
可以看到,无论是否使用hint都走索引了:
LUNAR@lunar>set autotrace on
LUNAR@lunar>select /*+ index(lunar IDX_LUNAR_EXTENT_ID) */ min(extent_id),max(extent_id) from lunar;
MIN(EXTENT_ID) MAX(EXTENT_ID)
-------------- --------------
0 61
Elapsed: 00:00:00.00
Execution Plan
----------------------------------------------------------
Plan hash value: 1897601393
----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 3 | 11 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 3 | | |
| 2 | INDEX FULL SCAN| IDX_LUNAR_EXTENT_ID | 5223 | 15669 | 11 (0)| 00:00:01 |
----------------------------------------------------------------------------------------
注意: 使用hint时,走的是“INDEX FULL SCAN”
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
11 consistent gets
0 physical reads
0 redo size
610 bytes sent via SQL*Net to client
524 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
LUNAR@lunar>select min(extent_id),max(extent_id) from lunar;
MIN(EXTENT_ID) MAX(EXTENT_ID)
-------------- --------------
0 61
Elapsed: 00:00:00.01
Execution Plan
----------------------------------------------------------
Plan hash value: 2695027278
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 3 | 4 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 3 | | |
| 2 | INDEX FAST FULL SCAN| IDX_LUNAR_EXTENT_ID | 5223 | 15669 | 4 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
注意: 不使用hint时,走的是“INDEX FAST FULL SCAN”
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
15 consistent gets
0 physical reads
0 redo size
610 bytes sent via SQL*Net to client
524 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
LUNAR@lunar>
再次验证,依然这个结果:
LUNAR@lunar>alter table lunar modify extent_id null;
Table altered.
Elapsed: 00:00:00.01
LUNAR@lunar>select min(extent_id),max(extent_id) from lunar;
MIN(EXTENT_ID) MAX(EXTENT_ID)
-------------- --------------
0 61
Elapsed: 00:00:00.01
Execution Plan
----------------------------------------------------------
Plan hash value: 291688323
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 3 | 16 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 3 | | |
| 2 | TABLE ACCESS FULL| LUNAR | 5223 | 15669 | 16 (0)| 00:00:01 |
----------------------------------------------------------------------------
Statistics
----------------------------------------------------------
22 recursive calls
0 db block gets
75 consistent gets
0 physical reads
0 redo size
610 bytes sent via SQL*Net to client
524 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
6 sorts (memory)
0 sorts (disk)
1 rows processed
LUNAR@lunar>
单独查询最小值或者最大值时,也可以走索引,采用“INDEX FULL SCAN (MIN/MAX)”:
LUNAR@lunar>select min(extent_id) from lunar;
MIN(EXTENT_ID)
--------------
0
Elapsed: 00:00:00.01
Execution Plan
----------------------------------------------------------
Plan hash value: 4158629481
--------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 3 | 2 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 3 | | |
| 2 | INDEX FULL SCAN (MIN/MAX)| IDX_LUNAR_EXTENT_ID | 1 | 3 | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
2 consistent gets
0 physical reads
0 redo size
531 bytes sent via SQL*Net to client
524 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
LUNAR@lunar>select max(extent_id) from lunar;
MAX(EXTENT_ID)
--------------
61
Elapsed: 00:00:00.01
Execution Plan
----------------------------------------------------------
Plan hash value: 4158629481
--------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 3 | 2 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 3 | | |
| 2 | INDEX FULL SCAN (MIN/MAX)| IDX_LUNAR_EXTENT_ID | 1 | 3 | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
2 consistent gets
0 physical reads
0 redo size
532 bytes sent via SQL*Net to client
524 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
LUNAR@lunar>
假设,在不能修改表结构的情况下,怎么才能让“select min(extent_id),max(extent_id) from lunar”走索引呢?
参考了网上的一些建议,改写sql如下:
LUNAR@lunar>select
2 (select min(extent_id) from lunar) as min_extent_id,
3 (select max(extent_id) from lunar) as max_extent_id
4 from dual;
MIN_EXTENT_ID MAX_EXTENT_ID
------------- -------------
0 61
Elapsed: 00:00:00.01
Execution Plan
----------------------------------------------------------
Plan hash value: 778639039
--------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 2 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 3 | | |
| 2 | INDEX FULL SCAN (MIN/MAX)| IDX_LUNAR_EXTENT_ID | 1 | 3 | 2 (0)| 00:00:01 |
| 3 | SORT AGGREGATE | | 1 | 3 | | |
| 4 | INDEX FULL SCAN (MIN/MAX)| IDX_LUNAR_EXTENT_ID | 1 | 3 | 2 (0)| 00:00:01 |
| 5 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
4 consistent gets
0 physical reads
0 redo size
608 bytes sent via SQL*Net to client
524 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
LUNAR@lunar>
