今天在网上看到一道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。

  不知道是不是还有更好的优化方法,目前能想到的就这个了,如果有更好的,希望大家指点。