测试组合索引

测试背景:生产数据库的会员表和产品表中存在三个CLOB字段(这些字段主要用来存会员和产品的描述信息),随着数据量的增长,全表扫描的时候,I/O等待严重,于是想到分表!

提出问题:这两张大表,加起来的索引总共有35个,其中会员表的索引数为17个,产品表的索引数为18个(35个索引中不包含LOB字段的索引),这些索引大部分为组合索引,且存在函数索引(函数索引均为组合索引的前导列进行desc排序)

索引优化测试:在测试库中进行优化测试,原始会员表用test代替,用户schema用hr代替,数据库版本为11.2.0.3 32bit on widows2003 enterprise edition

一:建表,添加主键约束和组合索引1

  
  
  
  
  1. SQL> create table t1 as select * from test;  
  2.  
  3. SQL> alter table t1 add constraint pk_t1_id primary key (id);  
  4. Table altered.  
  5.  
  6. SQL> create index idx_t1_mul1 on t1(status,registersource);  
  7. Index created. 

二:收集表统计信息,对status字段的空值进行赋值,status字段为会员的状态,1为正常状态,其他值均为异常状态,所以值的分布倾斜

  
  
  
  
  1. SQL> update t1 set status=0 where status is null;  
  2. 4 rows updated.  
  3.  
  4. SQL> commit;  
  5. Commit complete.  
  6.  
  7. SQL> exec dbms_stats.gather_table_stats(‘HR’,'T1',CASCADE=>true);  
  8. PL/SQL procedure successfully completed.  
  9.  
  10. SQL> select status,count(*) from t1 group by status;  
  11.  
  12.     STATUS   COUNT(*)  
  13. ---------- ----------  
  14.          1     595612  
  15.          2       1230  
  16.          4         10  
  17.          5          1  
  18.          3       2746  
  19.          0      26825  
  20. 6 rows selected. 

三:测试证明结果集比较小的情况下,where字句中包含前导列的时候就会使用组合索引

  
  
  
  
  1. SQL> select id,version from t1 where status=0;  
  2.  
  3. Execution Plan  
  4. ----------------------------------------------------------  
  5. Plan hash value: 1745128362  
  6. -------------------------------------------------------------------------------------------  
  7. | Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)|Time    |  
  8. -------------------------------------------------------------------------------------------  
  9. |   0 | SELECT STATEMENT            |             | 26939 |   289K|  6051   (1)|00:01:13 |  
  10. |   1 |  TABLE ACCESS BY INDEX ROWID| T1          | 26939 |   289K|  6051   (1)|00:01:13 |  
  11. |*  2 |   INDEX RANGE SCAN          | IDX_T1_MUL1 | 26939 |       |    93   (0)|00:00:02 |  
  12. -------------------------------------------------------------------------------------------  
  13. Predicate Information (identified by operation id):  
  14. ---------------------------------------------------  
  15.    2 - access("STATUS"=0) 

四:建组合索引2(组合索引2的字段同组合索引1一样,只是前导列对调),对registersource字段的空值进行赋值,收集表的统计信息;(该字段用来存储用户的注册来源,值分布也存在倾斜的情况)

  
  
  
  
  1. SQL> create index idx_t1_mul2 on t1(registersource,status);  
  2. Index created.  
  3.  
  4. SQL> select registersource,count(*) from t1 group by registersource;  
  5.  
  6. REGIST   COUNT(*)  
  7. ------ ----------  
  8. 1             156  
  9.                 4  
  10. 3            1689  
  11. 6               4  
  12. 0           23487  
  13. 2          601084  
  14. 6 rows selected.  
  15.  
  16. SQL> update t1 set registersource=6 where registersource is null;  
  17. 4 rows updated  
  18.  
  19. SQL>commit;  
  20. Commit complete.  
  21.  
  22. SQL> exec dbms_stats.gather_table_stats(‘HR’,'T1',CASCADE=>true);  
  23. PL/SQL procedure successfully completed. 

五:只查询registersource字段且结果集小的时候,执行计划采用组合索引2 

  
  
  
  
  1. SQL> select  * from t1 where registersource='1'; //这里registersource字段为varchar2类型,故而加引号  
  2.  
  3. Execution Plan  
  4. ----------------------------------------------------------  
  5. Plan hash value: 2744963562  
  6. -------------------------------------------------------------------------------------------  
  7. | Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)|Time     |  
  8. -------------------------------------------------------------------------------------------  
  9. |   0 | SELECT STATEMENT            |             |   227 |   287K|    49   (0)|00:00:01 |  
  10. |   1 |  TABLE ACCESS BY INDEX ROWID| T1          |   227 |   287K|    49   (0)|00:00:01 |  
  11. |*  2 |   INDEX RANGE SCAN          | IDX_T1_MUL2 |   227 |       |     3   (0)|00:00:01 |  
  12. ------------------------------------------------------------------------------------------  
  13. Predicate Information (identified by operation id):  
  14. ---------------------------------------------------  
  15.    2 - access("REGISTERSOURCE"='1') 

六:倾斜组合测试

  
  
  
  
  1. 1:小小  
  2. SQL> select * from t1 where status=0 and registersource=0;  
  3.  
  4. Execution Plan  
  5. ----------------------------------------------------------  
  6. Plan hash value: 1745128362  
  7. -------------------------------------------------------------------------------------------  
  8. | Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)|Time    |  
  9. -------------------------------------------------------------------------------------------  
  10. |   0 | SELECT STATEMENT            |             |  1057 |  1337K|   280   (0)|00:00:04 |  
  11. |   1 |  TABLE ACCESS BY INDEX ROWID| T1          |  1057 |  1337K|   280   (0)|00:00:04 |  
  12. |*  2 |   INDEX RANGE SCAN          | IDX_T1_MUL1 |  1057 |       |    68   (0)|00:00:01 |  
  13. -------------------------------------------------------------------------------------------  
  14. Predicate Information (identified by operation id):  
  15. ---------------------------------------------------  
  16.    2 - access("STATUS"=0)  
  17.        filter(TO_NUMBER("REGISTERSOURCE")=0)  
  18.  
  19. SQL> select * from t1 where registersource=0 and status=0;  
  20.  
  21. Execution Plan  
  22. ----------------------------------------------------------  
  23. Plan hash value: 1745128362  
  24. -------------------------------------------------------------------------------------------  
  25. | Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)|Time    |  
  26. -------------------------------------------------------------------------------------------  
  27. |   0 | SELECT STATEMENT            |             |  1057 |  1337K|   280   (0)|00:00:04 |  
  28. |   1 |  TABLE ACCESS BY INDEX ROWID| T1          |  1057 |  1337K|   280   (0)|00:00:04 |  
  29. |*  2 |   INDEX RANGE SCAN          | IDX_T1_MUL1 |  1057 |       |    68   (0)|00:00:01 |  
  30. -------------------------------------------------------------------------------------------  
  31. Predicate Information (identified by operation id):  
  32. ---------------------------------------------------  
  33.    2 - access("STATUS"=0)  
  34.        filter(TO_NUMBER("REGISTERSOURCE")=0)  
  35.  
  36. 2:小大  
  37. SQL> select * from t1 where status=0 and registersource=2;  
  38.  
  39. Execution Plan  
  40. ----------------------------------------------------------  
  41. Plan hash value: 1745128362  
  42. -------------------------------------------------------------------------------------------  
  43. | Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)|Time    |  
  44. -------------------------------------------------------------------------------------------  
  45. |   0 | SELECT STATEMENT            |             | 28531 |    35M|  5776   (1)|00:01:10 |  
  46. |   1 |  TABLE ACCESS BY INDEX ROWID| T1          | 28531 |    35M|  5776   (1)|00:01:10 |  
  47. |*  2 |   INDEX RANGE SCAN          | IDX_T1_MUL1 | 28531 |       |    68   (0)|00:00:01 |  
  48. -------------------------------------------------------------------------------------------  
  49. Predicate Information (identified by operation id):  
  50. ---------------------------------------------------  
  51.    2 - access("STATUS"=0)  
  52.        filter(TO_NUMBER("REGISTERSOURCE")=2)  
  53.  
  54. SQL> select * from t1 where  registersource=2 and status=0;  
  55.  
  56. Execution Plan  
  57. ----------------------------------------------------------  
  58. Plan hash value: 1745128362  
  59. -------------------------------------------------------------------------------------------  
  60. | Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)| Time   |  
  61. -------------------------------------------------------------------------------------------  
  62. |   0 | SELECT STATEMENT            |             | 28531 |    35M|  5776   (1)|00:01:10 |  
  63. |   1 |  TABLE ACCESS BY INDEX ROWID| T1          | 28531 |    35M|  5776   (1)|00:01:10 |  
  64. |*  2 |   INDEX RANGE SCAN          | IDX_T1_MUL1 | 28531 |       |    68   (0)|00:00:01 |  
  65. -------------------------------------------------------------------------------------------  
  66. Predicate Information (identified by operation id):  
  67. ---------------------------------------------------  
  68.    2 - access("STATUS"=0)  
  69.        filter(TO_NUMBER("REGISTERSOURCE")=2)  
  70.  
  71. 3:大小  
  72. SQL> select * from t1 where status=1 and registersource=0;  
  73.  
  74. Execution Plan  
  75. ----------------------------------------------------------  
  76. Plan hash value: 1106331959  
  77. -------------------------------------------------------------------------------------------  
  78. | Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)|Time    |  
  79. -------------------------------------------------------------------------------------------  
  80. |   0 | SELECT STATEMENT            |             | 21105 |    26M|  4659   (1)|00:00:56 |  
  81. |   1 |  TABLE ACCESS BY INDEX ROWID| T1          | 21105 |    26M|  4659   (1)|00:00:56 |  
  82. |*  2 |   INDEX SKIP SCAN           | IDX_T1_MUL2 | 21105 |       |   437   (0)|00:00:06 |  
  83. ------------------------------------------------------------------------------------------  
  84. Predicate Information (identified by operation id):  
  85. ---------------------------------------------------  
  86.    2 - access("STATUS"=1)  
  87.        filter(TO_NUMBER("REGISTERSOURCE")=0 AND "STATUS"=1)  
  88.  
  89. SQL> select * from t1 where  registersource=0 and status=1;  
  90.  
  91. Execution Plan  
  92. ----------------------------------------------------------  
  93. Plan hash value: 1106331959  
  94. -------------------------------------------------------------------------------------------  
  95. | Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)|Time    |  
  96. -------------------------------------------------------------------------------------------  
  97. |   0 | SELECT STATEMENT            |             | 21105 |    26M|  4659   (1)|00:00:56 |  
  98. |   1 |  TABLE ACCESS BY INDEX ROWID| T1          | 21105 |    26M|  4659   (1)|00:00:56 |  
  99. |*  2 |   INDEX SKIP SCAN           | IDX_T1_MUL2 | 21105 |       |   437   (0)|00:00:06 |  
  100. -------------------------------------------------------------------------------------------  
  101. Predicate Information (identified by operation id):  
  102. ---------------------------------------------------  
  103.    2 - access("STATUS"=1)  
  104.        filter(TO_NUMBER("REGISTERSOURCE")=0 AND "STATUS"=1)  
  105.  
  106. 4:大大  
  107. SQL> select * from t1 where status=1 and registersource=2;  
  108.  
  109. Execution Plan  
  110. ----------------------------------------------------------  
  111. Plan hash value: 3617692013  
  112. --------------------------------------------------------------------------  
  113. | Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |  
  114. --------------------------------------------------------------------------  
  115. |   0 | SELECT STATEMENT  |      |   569K|   703M| 32570   (1)| 00:06:31 |  
  116. |*  1 |  TABLE ACCESS FULL| T1   |   569K|   703M| 32570   (1)| 00:06:31 |  
  117. --------------------------------------------------------------------------  
  118.  
  119. Predicate Information (identified by operation id):  
  120. ---------------------------------------------------  
  121.    1 - filter("STATUS"=1 AND TO_NUMBER("REGISTERSOURCE")=2)  
  122.  
  123. SQL> select * from t1 where  registersource=2 and status=1;  
  124. Execution Plan  
  125. ----------------------------------------------------------  
  126. Plan hash value: 3617692013  
  127. --------------------------------------------------------------------------  
  128. | Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |  
  129. --------------------------------------------------------------------------  
  130. |   0 | SELECT STATEMENT  |      |   569K|   703M| 32570   (1)| 00:06:31 |  
  131. |*  1 |  TABLE ACCESS FULL| T1   |   569K|   703M| 32570   (1)| 00:06:31 |  
  132. --------------------------------------------------------------------------  
  133.  
  134. Predicate Information (identified by operation id):  
  135. ---------------------------------------------------  
  136.    1 - filter("STATUS"=1 AND TO_NUMBER("REGISTERSOURCE")=2) 

测试结果表明,cbo将根据结果集的大小来决定使用最优的执行计划

七:组合索引和其他字段的配合使用(测试结果说明where子句中包含组合索引的前导列,且结果集小的情况下,执行计划会选择走组合索引)

  
  
  
  
  1. SQL> select * from t1 where status=0 and createddate < sysdate;  
  2. Execution Plan  
  3. ----------------------------------------------------------  
  4. Plan hash value: 1745128362  
  5. -------------------------------------------------------------------------------------------  
  6. | Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)| Time     |  
  7. -------------------------------------------------------------------------------------------  
  8. |   0 | SELECT STATEMENT            |             | 29698 |    36M|  6009   (1)|00:01:13 |  
  9. |*  1 |  TABLE ACCESS BY INDEX ROWID| T1          | 29698 |    36M|  6009   (1)|00:01:13 |  
  10. |*  2 |   INDEX RANGE SCAN          | IDX_T1_MUL1 | 29698 |       |    68   (0)|00:00:01 |  
  11. -------------------------------------------------------------------------------------------  
  12. Predicate Information (identified by operation id):  
  13. ---------------------------------------------------  
  14.  
  15.    1 - filter("CREATEDDATE"<SYSDATE@!)  
  16.    2 - access("STATUS"=0)  
  17.  
  18. SQL> select * from t1 where registersource='0' and createddate < sysdate;  
  19.  
  20. Execution Plan  
  21. ----------------------------------------------------------  
  22. Plan hash value: 2744963562  
  23. -------------------------------------------------------------------------------------------  
  24. | Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)| Time     |  
  25. -------------------------------------------------------------------------------------------  
  26. |   0 | SELECT STATEMENT            |             | 22302 |    27M|  4514   (1)|00:00:55 |  
  27. |*  1 |  TABLE ACCESS BY INDEX ROWID| T1          | 22302 |    27M|  4514   (1)|00:00:55 |  
  28. |*  2 |   INDEX RANGE SCAN          | IDX_T1_MUL2 | 22302 |       |    52   (0)|00:00:01 |  
  29. -------------------------------------------------------------------------------------------  
  30. Predicate Information (identified by operation id):  
  31. ---------------------------------------------------  
  32.    1 - filter("CREATEDDATE"<SYSDATE@!)  
  33.    2 - access("REGISTERSOURCE"='0') 

八:函数索引测试,对orderno,membership.status,featured四个字段建组合索引3,同时orderno字段进行desc排序;对前面4个字段建立普通的组合索引4,这种做法意在测试是否有必要使用函数索引?

  
  
  
  
  1. SQL> create index idx_t1_mul3 on t1(orderno desc,membership,status,featured);  
  2. Index created.  
  3.  
  4. SQL> select * from t1 where membership=1 and status=0 order by orderno;  
  5. no rows selected  
  6.  
  7. Execution Plan  
  8. ----------------------------------------------------------  
  9. Plan hash value: 687259109  
  10. -------------------------------------------------------------------------------------------  
  11. | Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)|Time     |  
  12. -------------------------------------------------------------------------------------------  
  13. |   0 | SELECT STATEMENT            |             |  5940 |  7517K|  3009   (1)|00:00:37 |  
  14. |   1 |  TABLE ACCESS BY INDEX ROWID| T1          |  5940 |  7517K|  3009   (1)|00:00:37 |  
  15. |*  2 |   INDEX FULL SCAN DESCENDING| IDX_T1_MUL3 |  5940 |       |  1825   (1)|00:00:22 |  
  16. -------------------------------------------------------------------------------------------  
  17. Predicate Information (identified by operation id):  
  18. ---------------------------------------------------  
  19.  
  20.    2 - access("MEMBERSHIP"=1 AND "STATUS"=0)  
  21.        filter("STATUS"=0 AND "MEMBERSHIP"=1)  
  22.  
  23. SQL> select * from t1 where membership=1 and status=0 order by orderno desc;  
  24. no rows selected  
  25.  
  26. Execution Plan  
  27. ----------------------------------------------------------  
  28. Plan hash value: 607735922  
  29. -------------------------------------------------------------------------------------------  
  30. | Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)|Time     |  
  31. -------------------------------------------------------------------------------------------  
  32. |   0 | SELECT STATEMENT            |             |  5940 |  7517K|  3009   (1)|00:00:37 |  
  33. |   1 |  TABLE ACCESS BY INDEX ROWID| T1          |  5940 |  7517K|  3009   (1)|00:00:37 |  
  34. |*  2 |   INDEX FULL SCAN           | IDX_T1_MUL3 |  5940 |       |  1825   (1)|00:00:22 |  
  35. -------------------------------------------------------------------------------------------  
  36. Predicate Information (identified by operation id):  
  37. ---------------------------------------------------  
  38.  
  39.    2 - access("MEMBERSHIP"=1 AND "STATUS"=0)  
  40.        filter("STATUS"=0 AND "MEMBERSHIP"=1)  
  41.  
  42. SQL> drop index idx_t1_mul3;  
  43. Index dropped.  
  44.  
  45. SQL> create index idx_t1_mul4 on t1(orderno,membership,status,featured);  
  46. Index created.  
  47.  
  48. SQL> select * from t1 where membership=1 and status=0 order by orderno;  
  49. no rows selected  
  50.  
  51. Execution Plan  
  52. ----------------------------------------------------------  
  53. Plan hash value: 3155127807  
  54. -------------------------------------------------------------------------------------------  
  55. | Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)|Time     |  
  56. -------------------------------------------------------------------------------------------  
  57. |   0 | SELECT STATEMENT            |             |  5940 |  7517K|  1923   (1)|00:00:24 |  
  58. |   1 |  TABLE ACCESS BY INDEX ROWID| T1          |  5940 |  7517K|  1923   (1)|00:00:24 |  
  59. |*  2 |   INDEX SKIP SCAN           | IDX_T1_MUL4 |  5940 |       |   739   (0)|00:00:09 |  
  60. -------------------------------------------------------------------------------------------  
  61. Predicate Information (identified by operation id):  
  62. ---------------------------------------------------  
  63.    2 - access("MEMBERSHIP"=1 AND "STATUS"=0)  
  64.        filter("STATUS"=0 AND "MEMBERSHIP"=1)  
  65.  
  66. SQL> select * from t1 where membership=1 and status=0 order by orderno desc;  
  67. no rows selected  
  68.  
  69. Execution Plan  
  70. ----------------------------------------------------------  
  71. Plan hash value: 893632694  
  72. -------------------------------------------------------------------------------------------  
  73. | Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)|Time     |  
  74. -------------------------------------------------------------------------------------------  
  75. |   0 | SELECT STATEMENT            |             |  5940 |  7517K|  1923   (1)|00:00:24 |  
  76. |   1 |  TABLE ACCESS BY INDEX ROWID| T1          |  5940 |  7517K|  1923   (1)|00:00:24 |  
  77. |*  2 |   INDEX SKIP SCAN DESCENDING| IDX_T1_MUL4 |  5940 |       |   739   (0)|00:00:09 |  
  78. -------------------------------------------------------------------------------------------  
  79. Predicate Information (identified by operation id):  
  80. ---------------------------------------------------  
  81.    2 - access("MEMBERSHIP"=1 AND "STATUS"=0)  
  82.        filter("STATUS"=0 AND "MEMBERSHIP"=1) 

从测试结果上看,不使用函数索引的效果较优,同时去掉这类的函数索引,会方便今后的shrink table操作

九:不使用前导列情况下,组合索引是否能正常使用?在前面测试函数索引的过程中,where条件中不含前导列,只是对结果集进行排序的时候使用前导列,执行计划选择组合索引,因而进行如下测试!

  
  
  
  
  1. SQL> create index idx_t1_mul5 on t1(password,signinid);  
  2. Index created.  
  3.  
  4. SQL> select * from (select signinid,count(*) from t1 group by signinid) where rownum<10;  
  5.  
  6. SIGNINID                                                       COUNT(*)  
  7. ------------------------------------------------------------ ----------  
  8. 000000yu                                                              1  
  9. 0000410265269                                                         1  
  10. 00006789                                                              1  
  11. 00009746                                                              1  
  12. 000113                                                                1  
  13. 0001mwm                                                               1  
  14. 0002081                                                               1  
  15. 000317                                                                1  
  16. 00032156688                                                           1  
  17.  
  18. 9 rows selected.  
  19.  
  20. SQL> select * from t1 where signinid='000000yu';  
  21.  
  22. Execution Plan  
  23. ----------------------------------------------------------  
  24. Plan hash value: 2246799375  
  25. -------------------------------------------------------------------------------------------  
  26. | Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)|Time     |  
  27. -------------------------------------------------------------------------------------------  
  28. |   0 | SELECT STATEMENT            |             |     1 |  1296 |  3706   (1)|00:00:45 |  
  29. |   1 |  TABLE ACCESS BY INDEX ROWID| T1          |     1 |  1296 |  3706   (1)|00:00:45 |  
  30. |*  2 |   INDEX SKIP SCAN           | IDX_T1_MUL5 |     1 |       |  3705   (1)|00:00:45 |  
  31. -------------------------------------------------------------------------------------------  
  32. Predicate Information (identified by operation id):  
  33. ---------------------------------------------------  
  34.  
  35.    2 - access("SIGNINID"='000000yu')  
  36.        filter("SIGNINID"='000000yu')  
  37.  
  38. SQL> select * from t1 where createddate < sysdate and signinid='000000yu';  
  39.  
  40. Execution Plan  
  41. ----------------------------------------------------------  
  42. Plan hash value: 2246799375  
  43. -------------------------------------------------------------------------------------------  
  44. | Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)|Time     |  
  45. -------------------------------------------------------------------------------------------  
  46. |   0 | SELECT STATEMENT            |             |     1 |  1296 |  3706   (1)|00:00:45 |  
  47. |*  1 |  TABLE ACCESS BY INDEX ROWID| T1          |     1 |  1296 |  3706   (1)|00:00:45 |  
  48. |*  2 |   INDEX SKIP SCAN           | IDX_T1_MUL5 |     1 |       |  3705   (1)|00:00:45 |  
  49. -------------------------------------------------------------------------------------------  
  50. Predicate Information (identified by operation id):  
  51. ---------------------------------------------------  
  52.  
  53.    1 - filter("CREATEDDATE"<SYSDATE@!)  
  54.    2 - access("SIGNINID"='000000yu')  
  55.        filter("SIGNINID"='000000yu') 

从测试结果上看,11.2.0.3版本的数据库,只要查询语句中包含组合索引的字段,且结果集较小的情况下,执行计划会选择组合索引!

十:在10.2.0.1版本的oracle上进行同样的测试,发现where子句中不出现组合索引的前导列的时候,执行计划不会选择组合索引!

(第9和第10的测试有点疑问,后期将继续测试,ref  http://t.askmaclean.com/viewthread.php?tid=1384&pid=7258&page=1&extra=page%3D1)

  
  
  
  
  1. SQL> create user test  identified by test;  
  2. User created.  
  3.  
  4. SQL> grant connect,resource,select_catalog_role to test;  
  5. Grant succeeded.  
  6.  
  7. SQL> conn test/test  
  8. Connected.  
  9.  
  10. SQL> create table t1 as select * from dba_objects;  
  11. Table created.  
  12.  
  13. SQL> create table t1 as select * from dba_objects;  
  14. Table created.  
  15.  
  16. SQL> desc t1;  
  17.  Name                                      Null?    Type  
  18.  ----------------------------------------- -------- ----------------------------  
  19.  OWNER                                              VARCHAR2(30)  
  20.  OBJECT_NAME                                        VARCHAR2(128)  
  21.  SUBOBJECT_NAME                                     VARCHAR2(30)  
  22.  OBJECT_ID                                          NUMBER  
  23.  DATA_OBJECT_ID                                     NUMBER  
  24.  OBJECT_TYPE                                        VARCHAR2(19)  
  25.  CREATED                                            DATE  
  26.  LAST_DDL_TIME                                      DATE  
  27.  TIMESTAMP                                          VARCHAR2(19)  
  28.  STATUS                                             VARCHAR2(7)  
  29.  TEMPORARY                                          VARCHAR2(1)  
  30.  GENERATED                                          VARCHAR2(1)  
  31.  SECONDARY                                          VARCHAR2(1)  
  32.  
  33. SQL> create index i_t1_mul1 on t1(object_id,object_type);  
  34. Index created.  
  35.  
  36. SQL> set autot traceonly exp  
  37. SQL> select * from t1 where object_id < 100;  
  38.  
  39. Execution Plan  
  40. ----------------------------------------------------------  
  41. Plan hash value: 1186876071  
  42. -----------------------------------------------------------------------------------------  
  43. | Id  | Operation                   | Name      | Rows  | Bytes | Cost (%CPU)| Time     |  
  44. -----------------------------------------------------------------------------------------  
  45. |   0 | SELECT STATEMENT            |           |    98 | 17346 |     4   (0)| 00:00:01 |  
  46. |   1 |  TABLE ACCESS BY INDEX ROWID| T1        |    98 | 17346 |     4   (0)| 00:00:01 |  
  47. |*  2 |   INDEX RANGE SCAN          | I_T1_MUL1 |    98 |       |     2   (0)| 00:00:01 |  
  48. -----------------------------------------------------------------------------------------  
  49. Predicate Information (identified by operation id):  
  50. ---------------------------------------------------  
  51.    2 - access("OBJECT_ID"<100)  
  52.  
  53. Note  
  54. -----  
  55.    - dynamic sampling used for this statement  
  56.  
  57.  
  58. SQL> select * from t1 where object_type='INDEX';  
  59.  
  60. Execution Plan  
  61. ----------------------------------------------------------  
  62. Plan hash value: 3617692013  
  63. --------------------------------------------------------------------------  
  64. | Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |  
  65. --------------------------------------------------------------------------  
  66. |   0 | SELECT STATEMENT  |      |   531 | 93987 |   159   (2)| 00:00:02 |  
  67. |*  1 |  TABLE ACCESS FULL| T1   |   531 | 93987 |   159   (2)| 00:00:02 |  
  68. --------------------------------------------------------------------------  
  69. Predicate Information (identified by operation id):  
  70. ---------------------------------------------------  
  71.    1 - filter("OBJECT_TYPE"='INDEX')  
  72.  
  73. Note  
  74. -----  
  75.    - dynamic sampling used for this statement  
  76.  
  77.  
  78. SQL> set autot off  
  79. SQL> select count(*) from t1;  
  80.  
  81.   COUNT(*)  
  82. ----------  
  83.      50380  
  84.  
  85. SQL> select object_type,count(*) from t1  group by object_type;  
  86.  
  87. OBJECT_TYPE           COUNT(*)  
  88. ------------------- ----------  
  89. CONSUMER GROUP               5  
  90. INDEX PARTITION            276  
  91. SEQUENCE                   143  
  92. QUEUE                       27  
  93. SCHEDULE                     1  
  94. TABLE PARTITION            128  
  95. RULE                         4  
  96. JAVA DATA                  306  
  97. PROCEDURE                   85  
  98. OPERATOR                    57  
  99. LOB PARTITION                1  
  100.  
  101. OBJECT_TYPE           COUNT(*)  
  102. ------------------- ----------  
  103. WINDOW                       2  
  104. LOB                        566  
  105. PACKAGE                    848  
  106. PACKAGE BODY               791  
  107. LIBRARY                    150  
  108. RULE SET                    19  
  109. PROGRAM                     12  
  110. TYPE BODY                  173  
  111. CONTEXT                      5  
  112. JAVA RESOURCE              770  
  113. XML SCHEMA                  26  
  114.  
  115. OBJECT_TYPE           COUNT(*)  
  116. ------------------- ----------  
  117. TRIGGER                    171  
  118. JOB CLASS                    2  
  119. UNDEFINED                    6  
  120. DIRECTORY                    9  
  121. DIMENSION                    5  
  122. MATERIALIZED VIEW            2  
  123. TABLE                     1636  
  124. INDEX                     1800  
  125. SYNONYM                  20026  
  126. VIEW                      3671  
  127. FUNCTION                   270  
  128.  
  129. OBJECT_TYPE           COUNT(*)  
  130. ------------------- ----------  
  131. WINDOW GROUP                 1  
  132. JAVA CLASS               16417  
  133. INDEXTYPE                   10  
  134. CLUSTER                     10  
  135. TYPE                      1926  
  136. RESOURCE PLAN                3  
  137. EVALUATION CONTEXT          14  
  138. JOB                          6  
  139. 41 rows selected.  
  140.  
  141. SQL> set autot traceonly exp  
  142. SQL> select /*+index(i_t1_mul1)*/ * from t1 where object_type='INDEX';  
  143.  
  144. Execution Plan  
  145. ----------------------------------------------------------  
  146. Plan hash value: 3617692013  
  147. --------------------------------------------------------------------------  
  148. | Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |  
  149. --------------------------------------------------------------------------  
  150. |   0 | SELECT STATEMENT  |      |   531 | 93987 |   159   (2)| 00:00:02 |  
  151. |*  1 |  TABLE ACCESS FULL| T1   |   531 | 93987 |   159   (2)| 00:00:02 |  
  152. --------------------------------------------------------------------------  
  153. Predicate Information (identified by operation id):  
  154. ---------------------------------------------------  
  155.    1 - filter("OBJECT_TYPE"='INDEX')  
  156.  
  157. Note  
  158. -----  
  159.    - dynamic sampling used for this statement 

综上所述:
1:可以对线上数据库的组合索引做优化,对于倾斜字段做前导列的组合索引,可以使用非倾斜字段做前导列,或者建立相同的索引,前导列对调;

2:取消相应的函数索引

3:删除不必要的组合索引,对经常在where子句中出现的字段建组合索引(例如查询1中where子句出现A,B,C,D四个字段,查询2中where子句出现A,B,C三个字段,且这个查询语句经常出现,这种条件下,只需要对A,B,C,D字段建组合索引即可,无需建2个索引)

4:注意索引的热点块问题,前面3的场景在并发严重的情况下,有可能会导致出现热点快,因而需要根据需求来适当调整

本文出自 “斩月” 博客,谢绝转载!

你可能感兴趣的:(测试,index,组合索引,函数索引)