SQL Tuning --通过创建Index性能提升40倍

  •  起因

上周四下午的时候收到Oracle DB的High Disk I/O Loading Session警示邮件,查找发现是如下这段SQL导致High Disk I/O:

SELECT * FROM CLW3014 WHERE AUDIT_DATE = (SELECT MAX(AUDIT_DATE)  AUDIT_DATE FROM CLW3014 WHERE BOOK_NO = :B3 AND COLUMN_NAME = :B2 AND ENTRY_OFFICE = :B1 AND AUDIT_TYPE = 'A') AND AUDIT_TYPE ='A' AND COLUMN_NAME = :B2 AND ENTRY_OFFICE = :B1

这里特意做个FLAG记录一下。

 

  • 结果

SQL Tuning后性能大幅度提升:

SQL运行时间:17s 下降到 0.4s

Cost开销:18976 下降到 1

Consistent gets为:86807 下降到 13

Physical reads为:86785 下降到 9

 

  • 首先查看该SQL的执行计划:

SQL> set autotrace traceonly

SQL> ......sql......

Elapsed: 00:00:16.77

Execution Plan

----------------------------------------------------------------------------------------------------------

| Id  | Operation                                                | Name                |Rows|Bytes|Cost (%CPU)| Time     |

----------------------------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT                           |                           |     1 |    178 |  18976   (1) |  00:03:48|

|*  1 |  TABLE ACCESS FULL                         | CLW3014           |     1 |    178 |  18975   (1) |  00:03:48|

|   2 |   SORT AGGREGATE                           |                            |     1 |      39 |                  |                |

|*  3 |    TABLE ACCESS BY INDEX ROWID | CLW3014           |     1 |      39 |          1   (0) |  00:00:01|

|*  4 |     INDEX RANGE SCAN                      | CLW3014_IDX_3|  10 |           |         1   (0) |  00:00:01|

------------------------------------------------------------------------------------------------------------

Statistics

-----------------------------------------------------------------

          1  recursive calls

          0  db block gets

      86807  consistent gets

      86785  physical reads

        128  redo size

       1441  bytes sent via SQL*Net to client

        365  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

          3  rows processed

通过查看执行计划,该子查询SQL通过 BOOK_NO = :B3 走的是Index(CLW3014_IDX_3)扫描查询,即:

SELECT MAX(AUDIT_DATE)  AUDIT_DATE FROM CLW3014 WHERE BOOK_NO = :B3 AND COLUMN_NAME = :B2 AND ENTRY_OFFICE = :B1 AND AUDIT_TYPE = 'A'

主SQL没有走Index扫面查询,全表扫描查询CLW3014(FULL TABLE SCAN CLW3014),性能参数:

运行时间为:17s

Cost为:18976

Consistent gets为:86807

Physical reads为:86785

  • 查看CLW3014该TABLE表结构:

看到有以AUDIT_TYPE和SOURCE_RECORD_SEQ两个栏位建立组合Index:

CLW3014_IDX_1 on CLW3014 (AUDIT_TYPE, SOURCE_RECORD_SEQ)

看到主SQL有where条件:AUDIT_TYPE ='A' ,为何不走Index(CLW3014_IDX_1)扫描查询呢,因为该TABLE的AUDIT_TYPE栏位值纵总共才三个:

所以对于AUDIT_TYPE栏位来说,重复性太高,缺少SOURCE_RECORD_SEQ栏位作为条件的话走Index(CLW3014_IDX_1)扫描性能会更差,Oracle自动选择了最优的FULL TABLE SCAN查询的方式。

  • 創建Index之後执行计划分析如下:

查看数据发现AUDIT_DATE栏位的值可重复性不高,如果以AUDIT_DATE栏位创建Index,则性能大大提升:

SQL> create index CLW3014_IDX_5 on CLW3014 (AUDIT_DATE) tablespace CLWIDX pctfree 10;

Index created.

SQL> set autotrace traceonly

SQL> ......sql......

Elapsed: 00:00:00.40

 

Execution Plan

------------------------------------------------------------------------------------------------------------

| Id  | Operation                                               | Name                 |Rows |Bytes|Cost (%CPU)| Time     |

------------------------------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT                          |                             |      1  |   178|           1   (0) | 00:00:01 |

|*  1 |  TABLE ACCESS BY INDEX ROWID   | CLW3014            |      1  |   178|           1   (0) | 00:00:01 |

|*  2 |   INDEX RANGE SCAN                        | CLW3014_IDX_5 |      5  |        |           1   (0) | 00:00:01 |

|   3 |    SORT AGGREGATE                          |                              |      1  |    39|                   |                |

|*  4 |     TABLE ACCESS BY INDEX ROWID| CLW3014             |      1  |    39|           1   (0) | 00:00:01 |

|*  5 |      INDEX RANGE SCAN                     | CLW3014_IDX_3 |    10  |        |           1   (0) | 00:00:01 |

-----------------------------------------------------------------------------------------------------------

Statistics

----------------------------------------------------------

          1  recursive calls

          0  db block gets

         13  consistent gets

          9  physical reads

          0  redo size

       1457  bytes sent via SQL*Net to client

        365  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

          3  rows processed

 

看到主子SQL都走Index扫面查询,性能参数:

运行时间为:0.4s

Cost为:1

Consistent gets为:13

Physical reads为:9

发布了22 篇原创文章 · 获赞 35 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/sinat_27431397/article/details/88954008
今日推荐