[20200303]降序索引疑问5.txt

来源:这里教程网 时间:2026-03-03 15:12:45 作者:

[20200303]降序索引疑问5.txt --//昨天在优化sql语句时遇到一条sql语句.也是使用order by desc. --//突然想起一些细节我自己以前没有注意到.必须认真考虑. --//语句大致如下,换成*,不然太长了. SELECT *  FROM (SELECT * FROM jcd this WHERE this.biaoshi =  :1  ORDER BY this.jcjs_time desc ) WHERE rownum <= :2; > @ bind_cap abnnf6rh06s6c '' SQL_ID        CHILD_NUMBER WAS NAME POSITION MAX_LENGTH LAST_CAPTURED       DATATYPE_STRING VALUE_STRING C30 ------------- ------------ --- ---- -------- ---------- ------------------- --------------- ------------ -------------- abnnf6rh06s6c            0 YES :1          1         22 2017-11-01 15:32:04 NUMBER          57                            YES :2          2         22 2017-11-01 15:32:04 NUMBER          200 --//疑问1:如果像上面的jcjs_time,如果jcjs_time 有NULL,NULL值是否优先输出.因为NULL不管什么number还是字符.在oracle的编码是0xFF. --//疑问2:也是我最关注的,如果查询写成如下: SELECT *  FROM (SELECT * FROM jcd this  ORDER BY this.jcjs_time desc ) WHERE rownum <= :2; --//建立jcjs_time的普通索引和降序索引,在有NULL值的情况下,降序索引是否有效. 1.环境: SCOTT@book> @ ver1 PORT_STRING                    VERSION        BANNER ------------------------------ -------------- -------------------------------------------------------------------------------- x86_64/Linux 2.4.xx            11.2.0.4.0     Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production create table t as select rownum id, trunc(dbms_random.value(1,100)) idx ,sysdate+rownum/1000-100 cr_date,rownum||lpad('x',100,'x') vc from dual connect by level<=10e5-100; insert into t select rownum+10e5-100 id, trunc(dbms_random.value(1,100)) idx ,NULL cr_date,rownum||lpad('x',100,'x') vc from dual connect by level<=100; commit ; create index i_t_idx_cr_date on t(idx ,cr_date); create index if_t_idx_cr_date on t(idx ,cr_date desc); --//分析略.Method_Opt => 'FOR ALL COLUMNS SIZE 1 ' 2.测试: SCOTT@book> alter session set statistics_level = all; Session altered. SCOTT@book> SELECT *  FROM (SELECT * FROM t WHERE idx = 42 ORDER BY cr_date desc ) WHERE rownum <=5;     ID IDX CR_DATE             VC ------ --- ------------------- ---------------------------------------------------------------------------------------------------------- 999913  42                     13xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 999884  42 2022-08-20 06:41:07 999884xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 999698  42 2022-08-20 02:13:16 999698xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 999543  42 2022-08-19 22:30:04 999543xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 999382  42 2022-08-19 18:38:14 999382xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx --//可以发现NULL在第1个。 Plan hash value: 2332835607 -------------------------------------------------------------------------------------------------------------------------------------------- | Id  | Operation                      | Name            | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers | -------------------------------------------------------------------------------------------------------------------------------------------- |   0 | SELECT STATEMENT               |                 |      1 |        |       |     8 (100)|          |      5 |00:00:00.01 |       9 | |*  1 |  COUNT STOPKEY                 |                 |      1 |        |       |            |          |      5 |00:00:00.01 |       9 | |   2 |   VIEW                         |                 |      1 |      6 |   642 |     8   (0)| 00:00:01 |      5 |00:00:00.01 |       9 | |   3 |    TABLE ACCESS BY INDEX ROWID | T               |      1 |  10101 |  1213K|     8   (0)| 00:00:01 |      5 |00:00:00.01 |       9 | |*  4 |     INDEX RANGE SCAN DESCENDING| I_T_IDX_CR_DATE |      1 |      6 |       |     3   (0)| 00:00:01 |      5 |00:00:00.01 |       4 | -------------------------------------------------------------------------------------------------------------------------------------------- SCOTT@book> SELECT *  FROM (SELECT /*+ index(t IF_T_IDX_CR_DATE )*/ * FROM t WHERE idx = 42 ORDER BY cr_date desc ) WHERE rownum <= 5;     ID IDX CR_DATE             VC ------ --- ------------------- ---------------------------------------------------------------------------------------------------------- 999913  42                     13xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 999884  42 2022-08-20 06:41:07 999884xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 999698  42 2022-08-20 02:13:16 999698xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 999543  42 2022-08-19 22:30:04 999543xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 999382  42 2022-08-19 18:38:14 999382xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Plan hash value: 313436017 -------------------------------------------------------------------------------------------------------------------------------------------- | Id  | Operation                     | Name             | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers | -------------------------------------------------------------------------------------------------------------------------------------------- |   0 | SELECT STATEMENT              |                  |      1 |        |       |     8 (100)|          |      5 |00:00:00.01 |       9 | |*  1 |  COUNT STOPKEY                |                  |      1 |        |       |            |          |      5 |00:00:00.01 |       9 | |   2 |   VIEW                        |                  |      1 |      6 |   642 |     8   (0)| 00:00:01 |      5 |00:00:00.01 |       9 | |   3 |    TABLE ACCESS BY INDEX ROWID| T                |      1 |  10101 |  1213K|     8   (0)| 00:00:01 |      5 |00:00:00.01 |       9 | |*  4 |     INDEX RANGE SCAN          | IF_T_IDX_CR_DATE |      1 |      6 |       |     3   (0)| 00:00:01 |      5 |00:00:00.01 |       4 | -------------------------------------------------------------------------------------------------------------------------------------------- --//可以发现排序时NULL在最前面。 3.测试2 drop index i_t_idx_cr_date ; drop index if_t_idx_cr_date; create index i_t_cr_date on t(cr_date); create index if_t_cr_date on t(cr_date desc); --//分析略.Method_Opt => 'FOR ALL COLUMNS SIZE 1 ' SCOTT@book> select index_name,index_type,blevel,leaf_blocks,distinct_keys,num_rows from dba_indexes where owner=user and table_name='T'; INDEX_NAME                     INDEX_TYPE                      BLEVEL LEAF_BLOCKS DISTINCT_KEYS   NUM_ROWS ------------------------------ --------------------------- ---------- ----------- ------------- ---------- I_T_CR_DATE                    NORMAL                               2        2653        999900     999900 IF_T_CR_DATE                   FUNCTION-BASED NORMAL                2        2793        999901    1000000 --//从NUM_ROWS,DISTINCT_KEYS就可以看出降序索引是包含NULL的。 SCOTT@book> SELECT *  FROM (SELECT * FROM t  ORDER BY cr_date desc ) WHERE rownum <= 5;     ID IDX CR_DATE             VC ------ --- ------------------- ----------------------------------------------------------------------------------------------------- 999901  77                     1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 999905   5                     5xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 999904  47                     4xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 999903  51                     3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 999902  19                     2xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Plan hash value: 3299198703 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | Id  | Operation               | Name | Starts | E-Rows |E-Bytes|E-Temp | Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers | Reads  |  OMem |  1Mem | Used-Mem | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |   0 | SELECT STATEMENT        |      |      1 |        |       |       | 32529 (100)|          |      5 |00:00:00.68 |   17897 |  16777 |       |       |          | |*  1 |  COUNT STOPKEY          |      |      1 |        |       |       |            |          |      5 |00:00:00.68 |   17897 |  16777 |       |       |          | |   2 |   VIEW                  |      |      1 |   1000K|   102M|       | 32529   (1)| 00:06:31 |      5 |00:00:00.68 |   17897 |  16777 |       |       |          | |*  3 |    SORT ORDER BY STOPKEY|      |      1 |   1000K|   117M|   130M| 32529   (1)| 00:06:31 |      5 |00:00:00.68 |   17897 |  16777 |  1683K|   633K| 1495K (0)| |   4 |     TABLE ACCESS FULL   | T    |      1 |   1000K|   117M|       |  4933   (1)| 00:01:00 |   1000K|00:00:00.23 |   17897 |  16777 |       |       |          | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- --//执行计划选择全表扫描。并没有使用索引,使用普通索引可能不行,因为cr_date有NULL值。而降序索引包含NULL的,也不会使用。 --//加入提示看看。 SELECT *  FROM (SELECT /*+ index(t IF_T_CR_DATE )*/ * FROM t ORDER BY cr_date desc ) WHERE rownum <= 5; Plan hash value: 3299198703 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | Id  | Operation               | Name | Starts | E-Rows |E-Bytes|E-Temp | Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers | Reads  |  OMem |  1Mem | Used-Mem | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |   0 | SELECT STATEMENT        |      |      1 |        |       |       | 32529 (100)|          |      5 |00:00:00.65 |   17897 |  16878 |       |       |          | |*  1 |  COUNT STOPKEY          |      |      1 |        |       |       |            |          |      5 |00:00:00.65 |   17897 |  16878 |       |       |          | |   2 |   VIEW                  |      |      1 |   1000K|   102M|       | 32529   (1)| 00:06:31 |      5 |00:00:00.65 |   17897 |  16878 |       |       |          | |*  3 |    SORT ORDER BY STOPKEY|      |      1 |   1000K|   117M|   130M| 32529   (1)| 00:06:31 |      5 |00:00:00.65 |   17897 |  16878 |  1683K|   633K| 1495K (0)| |   4 |     TABLE ACCESS FULL   | T    |      1 |   1000K|   117M|       |  4933   (1)| 00:01:00 |   1000K|00:00:00.22 |   17897 |  16878 |       |       |          | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- --//根本没有理会提示。 4.加入过滤排除NULL值看看。 SCOTT@book> SELECT *  FROM (SELECT * FROM t  where cr_date is not null ORDER BY cr_date desc ) WHERE rownum <= 5;     ID IDX CR_DATE             VC ------ --- ------------------- ---------------------------------------------------------------------------------------------------------- 999900  88 2022-08-20 07:04:09 999900xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 999899  23 2022-08-20 07:02:43 999899xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 999898  89 2022-08-20 07:01:16 999898xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 999897  24 2022-08-20 06:59:50 999897xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 999896  98 2022-08-20 06:58:23 999896xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Plan hash value: 3230194292 ------------------------------------------------------------------------------------------------------------------------------------------------ | Id  | Operation                     | Name        | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers | Reads  | ------------------------------------------------------------------------------------------------------------------------------------------------ |   0 | SELECT STATEMENT              |             |      1 |        |       |     4 (100)|          |      5 |00:00:00.01 |       6 |      1 | |*  1 |  COUNT STOPKEY                |             |      1 |        |       |            |          |      5 |00:00:00.01 |       6 |      1 | |   2 |   VIEW                        |             |      1 |      5 |   535 |     4   (0)| 00:00:01 |      5 |00:00:00.01 |       6 |      1 | |   3 |    TABLE ACCESS BY INDEX ROWID| T           |      1 |    999K|   117M|     4   (0)| 00:00:01 |      5 |00:00:00.01 |       6 |      1 | |*  4 |     INDEX FULL SCAN DESCENDING| I_T_CR_DATE |      1 |      5 |       |     3   (0)| 00:00:01 |      5 |00:00:00.01 |       4 |      1 | ------------------------------------------------------------------------------------------------------------------------------------------------ --//可以使用普通索引。 SCOTT@book> SELECT *  FROM (SELECT /*+ index(t IF_T_CR_DATE )*/ * FROM t where cr_date is not null ORDER BY cr_date desc ) WHERE rownum <= 5;     ID IDX CR_DATE             VC ------ --- ------------------- ---------------------------------------------------------------------------------------------------------- 999900  88 2022-08-20 07:04:09 999900xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 999899  23 2022-08-20 07:02:43 999899xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 999898  89 2022-08-20 07:01:16 999898xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 999897  24 2022-08-20 06:59:50 999897xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 999896  98 2022-08-20 06:58:23 999896xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Plan hash value: 3299198703 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | Id  | Operation               | Name | Starts | E-Rows |E-Bytes|E-Temp | Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers | Reads  |  OMem |  1Mem | Used-Mem | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |   0 | SELECT STATEMENT        |      |      1 |        |       |       | 32526 (100)|          |      5 |00:00:00.68 |   17897 |  16887 |       |       |          | |*  1 |  COUNT STOPKEY          |      |      1 |        |       |       |            |          |      5 |00:00:00.68 |   17897 |  16887 |       |       |          | |   2 |   VIEW                  |      |      1 |    999K|   102M|       | 32526   (1)| 00:06:31 |      5 |00:00:00.68 |   17897 |  16887 |       |       |          | |*  3 |    SORT ORDER BY STOPKEY|      |      1 |    999K|   117M|   130M| 32526   (1)| 00:06:31 |      5 |00:00:00.68 |   17897 |  16887 |  1683K|   633K| 1495K (0)| |*  4 |     TABLE ACCESS FULL   | T    |      1 |    999K|   117M|       |  4934   (1)| 00:01:00 |    999K|00:00:00.23 |   17897 |  16887 |       |       |          | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- --//提示无效,并且还导致执行计划选择全表扫描,oracle这优化器优化方式也真奇怪了。 --//从这里也可以看出oracle的降序索引"很傻".更加提示降序索引不能乱用,适用的场景很少。 5.总结: 1.NULL在排序desc没有指定的情况下优先输出。 2.降序索引的适用范围很窄。 6.补充测试: --//NULLS last 或者NULLs first的情况。 drop index i_t_cr_date; drop index if_t_cr_date; create index i_t_idx_cr_date on t(idx ,cr_date); create index if_t_idx_cr_date on t(idx ,cr_date desc); SCOTT@book> select index_name,index_type,blevel,leaf_blocks,distinct_keys,num_rows from dba_indexes where owner=user and table_name='T'; INDEX_NAME                     INDEX_TYPE                      BLEVEL LEAF_BLOCKS DISTINCT_KEYS   NUM_ROWS ------------------------------ --------------------------- ---------- ----------- ------------- ---------- I_T_IDX_CR_DATE                NORMAL                               2        3068        999964    1000000 IF_T_IDX_CR_DATE               FUNCTION-BASED NORMAL                2        3213        999964    1000000 SCOTT@book> SELECT *  FROM (SELECT * FROM t WHERE idx = 42 ORDER BY cr_date desc NULLS last ) WHERE rownum <=5;     ID IDX CR_DATE             VC ------ --- ------------------- ---------------------------------------------------------------------------------------------------------- 999884  42 2022-08-20 06:41:07 999884xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 999698  42 2022-08-20 02:13:16 999698xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 999543  42 2022-08-19 22:30:04 999543xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 999382  42 2022-08-19 18:38:14 999382xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 999340  42 2022-08-19 17:37:45 999340xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Plan hash value: 3299198703 ------------------------------------------------------------------------------------------------------------------------------------------------------------- | Id  | Operation               | Name | Starts | E-Rows |E-Bytes|E-Temp | Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |   0 | SELECT STATEMENT        |      |      1 |        |       |       |  5216 (100)|          |      5 |00:00:00.14 |   17897 |       |       |          | |*  1 |  COUNT STOPKEY          |      |      1 |        |       |       |            |          |      5 |00:00:00.14 |   17897 |       |       |          | |   2 |   VIEW                  |      |      1 |  10101 |  1055K|       |  5216   (1)| 00:01:03 |      5 |00:00:00.14 |   17897 |       |       |          | |*  3 |    SORT ORDER BY STOPKEY|      |      1 |  10101 |  1213K|  1360K|  5216   (1)| 00:01:03 |      5 |00:00:00.14 |   17897 | 22528 | 22528 |20480  (0)| |*  4 |     TABLE ACCESS FULL   | T    |      1 |  10101 |  1213K|       |  4933   (1)| 00:01:00 |  10225 |00:00:00.13 |   17897 |       |       |          | ------------------------------------------------------------------------------------------------------------------------------------------------------------- --//使用全表扫描。 --//加入提示后: SELECT *  FROM (SELECT /*+ index(t I_T_IDX_CR_DATE) */ * FROM t WHERE idx = 42 ORDER BY cr_date desc NULLS last ) WHERE rownum <=5; Plan hash value: 1786862719 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | Id  | Operation                      | Name            | Starts | E-Rows |E-Bytes|E-Temp | Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers | Reads  |  OMem |  1Mem | Used-Mem | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |   0 | SELECT STATEMENT               |                 |      1 |        |       |       |  8061 (100)|          |      5 |00:00:00.04 |    7806 |     35 |       |       |          | |*  1 |  COUNT STOPKEY                 |                 |      1 |        |       |       |            |          |      5 |00:00:00.04 |    7806 |     35 |       |       |          | |   2 |   VIEW                         |                 |      1 |  10101 |  1055K|       |  8061   (1)| 00:01:37 |      5 |00:00:00.04 |    7806 |     35 |       |       |          | |*  3 |    SORT ORDER BY STOPKEY       |                 |      1 |  10101 |  1213K|  1360K|  8061   (1)| 00:01:37 |      5 |00:00:00.04 |    7806 |     35 | 22528 | 22528 |20480  (0)| |   4 |     TABLE ACCESS BY INDEX ROWID| T               |      1 |  10101 |  1213K|       |  7779   (1)| 00:01:34 |  10225 |00:00:00.03 |    7806 |     35 |       |       |          | |*  5 |      INDEX RANGE SCAN          | I_T_IDX_CR_DATE |      1 |  10101 |       |       |    33   (0)| 00:00:01 |  10225 |00:00:00.01 |      35 |     34 |       |       |          | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --//实际上扫描索引(idx=42的全部),cost比前面全表扫描要高。 SELECT *  FROM (SELECT /*+ index(t IF_T_IDX_CR_DATE) */ * FROM t WHERE idx = 42 ORDER BY cr_date desc NULLS last ) WHERE rownum <=5; Plan hash value: 1966750027 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | Id  | Operation                      | Name             | Starts | E-Rows |E-Bytes|E-Temp | Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers | Reads  |  OMem |  1Mem | Used-Mem | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |   0 | SELECT STATEMENT               |                  |      1 |        |       |       |  8063 (100)|          |      5 |00:00:00.03 |    7807 |     35 |       |       |          | |*  1 |  COUNT STOPKEY                 |                  |      1 |        |       |       |            |          |      5 |00:00:00.03 |    7807 |     35 |       |       |          | |   2 |   VIEW                         |                  |      1 |  10101 |  1055K|       |  8063   (1)| 00:01:37 |      5 |00:00:00.03 |    7807 |     35 |       |       |          | |*  3 |    SORT ORDER BY STOPKEY       |                  |      1 |  10101 |  1213K|  1360K|  8063   (1)| 00:01:37 |      5 |00:00:00.03 |    7807 |     35 |  2048 |  2048 | 2048  (0)| |   4 |     TABLE ACCESS BY INDEX ROWID| T                |      1 |  10101 |  1213K|       |  7781   (1)| 00:01:34 |  10225 |00:00:00.02 |    7807 |     35 |       |       |          | |*  5 |      INDEX RANGE SCAN          | IF_T_IDX_CR_DATE |      1 |  10101 |       |       |    35   (0)| 00:00:01 |  10225 |00:00:00.01 |      36 |     35 |       |       |          | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --//可以使用,但是你对比前面的情况,可以发现使用降序索引毫无优势。 --//使用NULLS first设置实际上对于desc是缺省设置。 SELECT *  FROM (SELECT * FROM t WHERE idx = 42 ORDER BY cr_date desc NULLS first ) WHERE rownum<=5; Plan hash value: 2332835607 -------------------------------------------------------------------------------------------------------------------------------------------- | Id  | Operation                      | Name            | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers | -------------------------------------------------------------------------------------------------------------------------------------------- |   0 | SELECT STATEMENT               |                 |      1 |        |       |     8 (100)|          |      5 |00:00:00.01 |       9 | |*  1 |  COUNT STOPKEY                 |                 |      1 |        |       |            |          |      5 |00:00:00.01 |       9 | |   2 |   VIEW                         |                 |      1 |      6 |   642 |     8   (0)| 00:00:01 |      5 |00:00:00.01 |       9 | |   3 |    TABLE ACCESS BY INDEX ROWID | T               |      1 |  10101 |  1213K|     8   (0)| 00:00:01 |      5 |00:00:00.01 |       9 | |*  4 |     INDEX RANGE SCAN DESCENDING| I_T_IDX_CR_DATE |      1 |      6 |       |     3   (0)| 00:00:01 |      5 |00:00:00.01 |       4 | -------------------------------------------------------------------------------------------------------------------------------------------- --//即使提示看看。 SELECT *  FROM (SELECT /*+ index(t I_T_IDX_CR_DATE) */ * FROM t WHERE idx = 42 ORDER BY cr_date desc NULLS first ) WHERE rownum <=5; Plan hash value: 1786862719 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | Id  | Operation                      | Name            | Starts | E-Rows |E-Bytes|E-Temp | Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers | Reads  |  OMem |  1Mem | Used-Mem | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |   0 | SELECT STATEMENT               |                 |      1 |        |       |       |  8061 (100)|          |      5 |00:00:00.06 |    7806 |   1613 |       |       |          | |*  1 |  COUNT STOPKEY                 |                 |      1 |        |       |       |            |          |      5 |00:00:00.06 |    7806 |   1613 |       |       |          | |   2 |   VIEW                         |                 |      1 |  10101 |  1055K|       |  8061   (1)| 00:01:37 |      5 |00:00:00.06 |    7806 |   1613 |       |       |          | |*  3 |    SORT ORDER BY STOPKEY       |                 |      1 |  10101 |  1213K|  1360K|  8061   (1)| 00:01:37 |      5 |00:00:00.06 |    7806 |   1613 | 22528 | 22528 |20480  (0)| |   4 |     TABLE ACCESS BY INDEX ROWID| T               |      1 |  10101 |  1213K|       |  7779   (1)| 00:01:34 |  10225 |00:00:00.05 |    7806 |   1613 |       |       |          | |*  5 |      INDEX RANGE SCAN          | I_T_IDX_CR_DATE |      1 |  10101 |       |       |    33   (0)| 00:00:01 |  10225 |00:00:00.01 |      35 |     32 |       |       |          | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --//注意看不是INDEX RANGE SCAN DESCENDING,感觉oracle优化器还是不够智能。实际上正确的提示是:INDEX_DESC SELECT *  FROM (SELECT /*+ index_desc(t I_T_IDX_CR_DATE) */ * FROM t WHERE idx = 42 ORDER BY cr_date desc NULLS first ) WHERE rownum <=5; Plan hash value: 2332835607 -------------------------------------------------------------------------------------------------------------------------------------------- | Id  | Operation                      | Name            | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers | -------------------------------------------------------------------------------------------------------------------------------------------- |   0 | SELECT STATEMENT               |                 |      1 |        |       |     8 (100)|          |      5 |00:00:00.01 |       9 | |*  1 |  COUNT STOPKEY                 |                 |      1 |        |       |            |          |      5 |00:00:00.01 |       9 | |   2 |   VIEW                         |                 |      1 |      6 |   642 |     8   (0)| 00:00:01 |      5 |00:00:00.01 |       9 | |   3 |    TABLE ACCESS BY INDEX ROWID | T               |      1 |      6 |   738 |     8   (0)| 00:00:01 |      5 |00:00:00.01 |       9 | |*  4 |     INDEX RANGE SCAN DESCENDING| I_T_IDX_CR_DATE |      1 |  10101 |       |     3   (0)| 00:00:01 |      5 |00:00:00.01 |       4 | -------------------------------------------------------------------------------------------------------------------------------------------- SELECT *  FROM (SELECT /*+ index(t IF_T_IDX_CR_DATE) */ * FROM t WHERE idx = 42 ORDER BY cr_date desc NULLS first ) WHERE rownum <=5; Plan hash value: 313436017 ----------------------------------------------------------------------------------------------------------------------------------------------------- | Id  | Operation                     | Name             | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers | Reads  | ----------------------------------------------------------------------------------------------------------------------------------------------------- |   0 | SELECT STATEMENT              |                  |      1 |        |       |     8 (100)|          |      5 |00:00:00.01 |       9 |      3 | |*  1 |  COUNT STOPKEY                |                  |      1 |        |       |            |          |      5 |00:00:00.01 |       9 |      3 | |   2 |   VIEW                        |                  |      1 |      6 |   642 |     8   (0)| 00:00:01 |      5 |00:00:00.01 |       9 |      3 | |   3 |    TABLE ACCESS BY INDEX ROWID| T                |      1 |  10101 |  1213K|     8   (0)| 00:00:01 |      5 |00:00:00.01 |       9 |      3 | |*  4 |     INDEX RANGE SCAN          | IF_T_IDX_CR_DATE |      1 |      6 |       |     3   (0)| 00:00:01 |      5 |00:00:00.01 |       4 |      3 | ----------------------------------------------------------------------------------------------------------------------------------------------------- --//再补充index_desc的情况: SELECT *  FROM (SELECT /*+ index_desc(t I_T_IDX_CR_DATE) */ * FROM t WHERE idx = 42 ORDER BY cr_date desc NULLS last ) WHERE rownum <=5; Plan hash value: 669288848 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | Id  | Operation                       | Name            | Starts | E-Rows |E-Bytes|E-Temp | Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |   0 | SELECT STATEMENT                |                 |      1 |        |       |       |  8061 (100)|          |      5 |00:00:00.03 |    7806 |       |       |          | |*  1 |  COUNT STOPKEY                  |                 |      1 |        |       |       |            |          |      5 |00:00:00.03 |    7806 |       |       |          | |   2 |   VIEW                          |                 |      1 |  10101 |  1055K|       |  8061   (1)| 00:01:37 |      5 |00:00:00.03 |    7806 |       |       |          | |*  3 |    SORT ORDER BY STOPKEY        |                 |      1 |  10101 |  1213K|  1360K|  8061   (1)| 00:01:37 |      5 |00:00:00.03 |    7806 |  2048 |  2048 | 2048  (0)| |   4 |     TABLE ACCESS BY INDEX ROWID | T               |      1 |  10101 |  1213K|       |  7779   (1)| 00:01:34 |  10225 |00:00:00.02 |    7806 |       |       |          | |*  5 |      INDEX RANGE SCAN DESCENDING| I_T_IDX_CR_DATE |      1 |  10101 |       |       |    33   (0)| 00:00:01 |  10225 |00:00:00.01 |      35 |       |       |          | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --//提示有效,但是无法充分利用降序的特性优化语句。

相关推荐