ORACLE SOS

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5260|回复: 2

含is null sql语句优化

[复制链接]

1

主题

1

帖子

7

积分

新手上路

Rank: 1

积分
7
发表于 2014-3-15 23:42:39 | 显示全部楼层 |阅读模式
原sql语句与执行计划
  1. SQL> set autot trace
  2. SQL> WITH AL AS (SELECT * FROM XIFENFEI_LOG WHERE CLEAR_TIME IS NULL)
  3.    2 SELECT SWP.ID SWP_ID, AL.* FROM AL FULL OUTER JOIN XIFENFEI_LOG_SWAP SWP ON SWP.ID = AL.ID;

  4. 54 rows selected.


  5. Execution Plan
  6. ----------------------------------------------------------
  7. Plan hash value: 888046630

  8. ----------------------------------------------------------------------------------------------------------
  9. | Id  | Operation                  | Name                        | Rows  | Bytes | Cost (%CPU)| Time     |
  10. ----------------------------------------------------------------------------------------------------------
  11. |   0 | SELECT STATEMENT           |                             |    24 | 11064 | 24658   (2)| 00:04:56 |
  12. |   1 |  TEMP TABLE TRANSFORMATION |                             |       |       |            |     |
  13. |   2 |   LOAD AS SELECT           |                             |       |       |            |     |
  14. |*  3 |    TABLE ACCESS FULL       | XIFENFEI_LOG                |    23 |  2576 | 24652   (2)| 00:04:56 |
  15. |   4 |   VIEW                     |                             |    24 | 11064 |     6  (17)| 00:00:01 |
  16. |   5 |    UNION-ALL               |                             |       |       |            |     |
  17. |   6 |     NESTED LOOPS OUTER     |                             |    23 | 10465 |     2   (0)| 00:00:01 |
  18. |   7 |      VIEW                  |                             |    23 | 10304 |     2   (0)| 00:00:01 |
  19. |   8 |       TABLE ACCESS FULL    | SYS_TEMP_0FD9D6605_51B4E691 |    23 |  2576 |     2   (0)| 00:00:01 |
  20. |*  9 |      INDEX UNIQUE SCAN     | XIFENFEI_LOG_SWP_PK         |     1 |     7 |     0   (0)| 00:00:01 |
  21. |* 10 |     HASH JOIN ANTI         |                             |     1 |    20 |     4  (25)| 00:00:01 |
  22. |  11 |      INDEX FULL SCAN       | XIFENFEI_LOG_SWP_PK         |    20 |   140 |     1   (0)| 00:00:01 |
  23. |  12 |      VIEW                  |                             |    23 |   299 |     2   (0)| 00:00:01 |
  24. |  13 |       TABLE ACCESS FULL    | SYS_TEMP_0FD9D6605_51B4E691 |    23 |  2576 |     2   (0)| 00:00:01 |
  25. ----------------------------------------------------------------------------------------------------------


  26. Predicate Information (identified by operation id):
  27. ---------------------------------------------------

  28.    3 - filter("CLEAR_TIME" IS NULL)
  29.    9 - access("SWP"."ID"(+)="AL"."ID")
  30.   10 - access("SWP"."ID"="AL"."ID")


  31. Statistics
  32. ----------------------------------------------------------
  33.           2  recursive calls
  34.           8  db block gets
  35.      111504  consistent gets
  36.           1  physical reads
  37.         692  redo size
  38.        8075  bytes sent via SQL*Net to client
  39.         502  bytes received via SQL*Net from client
  40.           5  SQL*Net roundtrips to/from client
  41.           0  sorts (memory)
  42.           0  sorts (disk)
  43.          54  rows processed
复制代码
这里很明显占用资源多,执行时间长的都在XIFENFEI_LOG表的全表扫描上,而该表的where 条件是CLEAR_TIME is null.


分析CLEAR_TIME 列null值的分布

  1. SQL> SELECT count(*) FROM XIFENFEI_LOG WHERE CLEAR_TIME IS NULL;

  2.   COUNT(*)
  3. ----------
  4.         48

  5. SQL> SELECT count(*) FROM XIFENFEI_LOG WHERE CLEAR_TIME IS not NULL;

  6.   COUNT(*)
  7. ----------
  8.    6899211
复制代码
通过这里分析可以知道,CLEAR_TIME is null的值非常少,如果能够创建一个index,取到CLEAR_TIME 列null的值,那效率将非常搞.但是有oracle index只是的人都知道,B树index是不包含null列,因此一般性index无法满足该需求.这里思考创建含常数的复合index,而且把CLEAR_TIME放在前面,因为后面的常数一定存在,因此CLEAR_TIME中含有null的记录也就包含在该复合index中.

创建含常数复合index

  1. SQL> create index ind_XIFENFEI_LOG_null on XIFENFEI_LOG (CLEAR_TIME,0) online;

  2. Index created.
复制代码
再次查看执行计划

  1. SQL> WITH AL AS (SELECT * FROM XIFENFEI_LOG WHERE CLEAR_TIME IS NULL)
  2.   2  SELECT SWP.ID SWP_ID, AL.* FROM AL FULL OUTER JOIN XIFENFEI_LOG_SWAP SWP ON SWP.ID = AL.ID;

  3. 50 rows selected.


  4. Execution Plan
  5. ----------------------------------------------------------
  6. Plan hash value: 2359331571

  7. -------------------------------------------------------------------------------------------------------------
  8. | Id  | Operation                     | Name                        | Rows  | Bytes | Cost (%CPU)| Time     |
  9. -------------------------------------------------------------------------------------------------------------
  10. |   0 | SELECT STATEMENT              |                             |    24 | 11064 |    25   (4)| 00:00:01 |
  11. |   1 |  TEMP TABLE TRANSFORMATION    |                             |       |       |            |          |
  12. |   2 |   LOAD AS SELECT              |                             |       |       |            |          |
  13. |   3 |    TABLE ACCESS BY INDEX ROWID| XIFENFEI_LOG                |    23 |  2576 |    19   (0)| 00:00:01 |
  14. |*  4 |     INDEX RANGE SCAN          | IND_XIFENFEI_LOG_NULL       |    23 |       |     3   (0)| 00:00:01 |
  15. |   5 |   VIEW                        |                             |    24 | 11064 |     6  (17)| 00:00:01 |
  16. |   6 |    UNION-ALL                  |                             |       |       |            |          |
  17. |   7 |     NESTED LOOPS OUTER        |                             |    23 | 10465 |     2   (0)| 00:00:01 |
  18. |   8 |      VIEW                     |                             |    23 | 10304 |     2   (0)| 00:00:01 |
  19. |   9 |       TABLE ACCESS FULL       | SYS_TEMP_0FD9D660D_51B4E691 |    23 |  2576 |     2   (0)| 00:00:01 |
  20. |* 10 |      INDEX UNIQUE SCAN        | XIFENFEI_LOG_SWP_PK         |     1 |     7 |     0   (0)| 00:00:01 |
  21. |* 11 |     HASH JOIN ANTI            |                             |     1 |    20 |     4  (25)| 00:00:01 |
  22. |  12 |      INDEX FULL SCAN          | XIFENFEI_LOG_SWP_PK         |    20 |   140 |     1   (0)| 00:00:01 |
  23. |  13 |      VIEW                     |                             |    23 |   299 |     2   (0)| 00:00:01 |
  24. |  14 |       TABLE ACCESS FULL       | SYS_TEMP_0FD9D660D_51B4E691 |    23 |  2576 |     2   (0)| 00:00:01 |
  25. -------------------------------------------------------------------------------------------------------------

  26. Predicate Information (identified by operation id):
  27. ---------------------------------------------------

  28.    4 - access("CLEAR_TIME" IS NULL)
  29.   10 - access("SWP"."ID"(+)="AL"."ID")
  30.   11 - access("SWP"."ID"="AL"."ID")


  31. Statistics
  32. ----------------------------------------------------------
  33.           2  recursive calls
  34.           8  db block gets
  35.          33  consistent gets
  36.           1  physical reads
  37.         648  redo size
  38.        7688  bytes sent via SQL*Net to client
  39.         502  bytes received via SQL*Net from client
  40.           5  SQL*Net roundtrips to/from client
  41.           0  sorts (memory)
  42.           0  sorts (disk)
  43.          50  rows processed
复制代码
这里可以发现,该sql使用了创建的含常数的复合index,sql执行时间从4分56秒,提高到现在的1秒钟,逻辑读从当初的111504减小到现在的33,巧用含常数的复合索引使得sql执行效率极大提高.



参考:含is null sql语句优化   创建包含null值index
回复

使用道具 举报

2

主题

20

帖子

89

积分

注册会员

Rank: 2

积分
89
发表于 2014-3-17 14:53:10 | 显示全部楼层
飞总blog上的文章吧
回复 支持 反对

使用道具 举报

2

主题

9

帖子

102

积分

注册会员

Rank: 2

积分
102
发表于 2014-12-15 23:34:30 | 显示全部楼层
请问,你那个SQL语句的这种框框是怎么搞得。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|ORACLE SOS 技术论坛

GMT+8, 2024-4-20 00:07 , Processed in 0.021520 second(s), 20 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表