今天在网上看到一道SQL优化题目,关于select max(id),min(id) from xxx;的优化,自己做了下实验:
1.创建测试表:
create table max(id number,name varchar2(20));
2.插入100000数据:
declare
i number;
begin
for i in 1..100000
loop
insert into max values(i,'jdfjdkfkd');
end loop;
end;
/
3.首先查看select max(id) from max的执行计划:
SQL> set autotrace traceonly
SQL>
SQL>
SQL>
SQL>
SQL> select max(id) from test.max;
Execution Plan
----------------------------------------------------------
Plan hash value: 931352090
-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 13 | 84 (2)| 00:00:02 |
| 1 | SORT AGGREGATE | | 1 | 13 | | |
| 2 | INDEX FULL SCAN (MIN/MAX)| IDX_MAX_ID | 98866 | 1255K| | |
-----------------------------------------------------------------------------------------
Note
-----
- dynamic sampling used for this statement
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
2 consistent gets
0 physical reads
0 redo size
410 bytes sent via SQL*Net to client
400 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
3.查看select max(id),min(id) from max的执行计划
SQL> select max(id),min(id) from test.max;
Execution Plan
----------------------------------------------------------
Plan hash value: 805572646
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 13 | 84 (2)| 00:00:02 |
| 1 | SORT AGGREGATE | | 1 | 13 | | |
| 2 | TABLE ACCESS FULL| MAX | 98866 | 1255K| 84 (2)| 00:00:02 |
---------------------------------------------------------------------------
Note
-----
- dynamic sampling used for this statement
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
316 consistent gets
0 physical reads
0 redo size
470 bytes sent via SQL*Net to client
400 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
发现执行计划发生变化,使用了index full scan,因为要同时查找max,min值,无法通过index full scan (min/max)来获取了,那么想到的优化方法是想办法让查询使用index full scan(min/max)
SQL> select a.max,b.min from
2 (select max(id) max from test.max) a,(select min(id) min from test.max) b;
Execution Plan
----------------------------------------------------------
Plan hash value: 2218966858
-------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 26 | 169 (2)| 00:00:03 |
| 1 | NESTED LOOPS | | 1 | 26 | 169 (2)| 00:00:03 |
| 2 | VIEW | | 1 | 13 | 84 (2)| 00:00:02 |
| 3 | SORT AGGREGATE | | 1 | 13 | | |
| 4 | INDEX FULL SCAN (MIN/MAX)| IDX_MAX_ID | 98866 | 1255K| | |
| 5 | VIEW | | 1 | 13 | 84 (2)| 00:00:02 |
| 6 | SORT AGGREGATE | | 1 | 13 | | |
| 7 | INDEX FULL SCAN (MIN/MAX)| IDX_MAX_ID | 98866 | 1255K| | |
-------------------------------------------------------------------------------------------
Note
-----
- dynamic sampling used for this statement
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
4 consistent gets
0 physical reads
0 redo size
462 bytes sent via SQL*Net to client
400 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
这样使用了两次index full scan(min/max),逻辑读下降到4。
不知道是不是还有更好的优化方法,目前能想到的就这个了,如果有更好的,希望大家指点。