改写不走索引的SQL

简介: 如下SQL为保证所有数据都出自UP_LOAD_SERL10表(后面将以别名T3称呼此表,其他表也已别名称呼) SELECT        T1.SERL_NO       ,T1.

如下SQL为保证所有数据都出自UP_LOAD_SERL10表(后面将以别名T3称呼此表,其他表也已别名称呼)
SELECT
       T1.SERL_NO
      ,T1.SI_YMD
      ,T1.ST_YMD
      ,T1.ST2_YMD
      ,T1.SO_YMD  
      ,T1.ACTU_DT    FOTA_DT
      ,T2.SALE_YMD  CHANEL_SO
      ,T2.REGI_DT   CHANEL_SO_REGI_DT
FROM MCS_BI.RW_BI_FT_LT T1
    ,MCS_HQ.HI_SALE_CHNL T2 
,MCS_HQ_READ.UP_LOAD_SERL10 T3
WHERE T1.SERL_NO = T2.SERL_NO(+)
AND   T3.SERL_NO = T1.SERL_NO(+);
此SQL运行足有5分钟,T1和T2表数据非常大足都超过千万行,而T3数据很小只有60行,为实现需要得出的结果,三个表在一起必须使用外连接,执行计划如下
Plan hash value: 3150097070

----------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                           | Name              | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Reads  |
----------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                    |                   |      1 |        |     63 |00:01:35.15 |    1173K|   1173K|
|   1 |  NESTED LOOPS OUTER                 |                   |      1 |     63 |     63 |00:01:35.15 |    1173K|   1173K|
|*  2 |   HASH JOIN OUTER                   |                   |      1 |     63 |     63 |00:01:34.96 |    1173K|   1173K|
|   3 |    TABLE ACCESS FULL                | UP_LOAD_SERL10    |      1 |     63 |     63 |00:00:00.01 |       7 |      0 |
|   4 |    PARTITION RANGE ALL              |                   |      1 |     38M|     38M|00:01:13.83 |    1173K|   1173K|
|   5 |     TABLE ACCESS FULL               | RW_BI_FT_LT       |    122 |     38M|     38M|00:01:03.25 |    1173K|   1173K|
|   6 |   TABLE ACCESS BY GLOBAL INDEX ROWID| HI_SALE_CHNL      |     63 |      1 |     63 |00:00:00.19 |     191 |     24 |
|*  7 |    INDEX UNIQUE SCAN                | UX_HI_SALE_CHNL_1 |     63 |      1 |     63 |00:00:00.19 |     128 |     24 |
----------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("T3"."SERL_NO"="T1"."SERL_NO")
   7 - access("T1"."SERL_NO"="T2"."SERL_NO")

Note
-----
   - dynamic sampling used for this statement (level=2)
由于是三个表做外连接,两个连接条件必须同时满足,且T3表又是最小的,优化器选择T1表和T3表先做HASH JOIN OUTER,然后与T1做NEST LOOP OUTER,从计划中可以看出T3和T1做外连接时,T1,T3表的SERL_NO上都没有索引,所以对应都是全表扫描,而T1和T2连接时,T2的SERL_NO上有索引,所以先做了INDEX UNIQUE SCAN,然后通过ROWID回表扫描。这里T1表的返回行数巨大,全表扫描必然很慢,因此应该想办法让T3和T1表连接时,T1的字段能走索引,查看T1表发现上面有主键索引 PK_INDEX 且索引包括两个字段 FOTA_SO_YMD, SERL_NO,因此优化器并没有使用到此索引,于是选择优化方式可以改写SQL让优化器便于查找表上的索引并能使用,对SQl采用如下改写

WITH T_MAST AS (
SELECT T1.SERL_NO
      ,T1.SI_YMD
      ,T1.ST_YMD
      ,T1.ST2_YMD
      ,T1.SO_YMD  
      ,T1.ACTU_DT    FOTA_DT
      ,T2.SALE_YMD  CHANEL_SO
      ,T2.REGI_DT   CHANEL_SO_REGI_DT
FROM MCS_BI.RW_BI_FT_LT T1
    ,MCS_HQ.HI_SALE_CHNL T2
WHERE T1.SERL_NO = T2.SERL_NO(+)
)
SELECT T_MAST.*   
FROM T_MAST,    
     MCS_HQ_READ.UP_LOAD_SERL10 T2
WHERE    T_MAST.SERL_NO(+) = T2.SERL_NO;

对应执行计划
Plan hash value: 2281879921

------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                             | Name              | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Reads  |
------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                      |                   |      1 |        |     63 |00:00:23.39 |   96374 |   2705 |
|   1 |  NESTED LOOPS OUTER                   |                   |      1 |     63 |     63 |00:00:23.39 |   96374 |   2705 |
|   2 |   TABLE ACCESS FULL                   | UP_LOAD_SERL10    |      1 |     63 |     63 |00:00:00.01 |       7 |      0 |
|   3 |   VIEW PUSHED PREDICATE               |                   |     63 |      1 |     63 |00:00:23.39 |   96367 |   2705 |
|   4 |    NESTED LOOPS OUTER                 |                   |     63 |      1 |     63 |00:00:23.39 |   96367 |   2705 |
|   5 |     PARTITION RANGE ALL               |                   |     63 |      1 |     63 |00:00:23.17 |   96183 |   2679 |
|   6 |      TABLE ACCESS BY LOCAL INDEX ROWID| RW_BI_FT_LT       |   7686 |      1 |     63 |00:00:23.16 |   96183 |   2679 |
|*  7 |       INDEX SKIP SCAN                 | PK_RW_BI_FT_LT    |   7686 |      1 |     63 |00:00:22.93 |   96121 |   2632 |
|   8 |     TABLE ACCESS BY GLOBAL INDEX ROWID| HI_SALE_CHNL      |     63 |      1 |     63 |00:00:00.22 |     184 |     26 |
|*  9 |      INDEX UNIQUE SCAN                | UX_HI_SALE_CHNL_1 |     63 |      1 |     63 |00:00:00.22 |     121 |     26 |
------------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   7 - access("T1"."SERL_NO"="T2"."SERL_NO")
       filter("T1"."SERL_NO"="T2"."SERL_NO")
   9 - access("T2"."SERL_NO"="T2"."SERL_NO")
       filter("T1"."SERL_NO"="T2"."SERL_NO")

Note
-----
   - dynamic sampling used for this statement (level=2)

这样原T1,T2关联时就可以使用字段中SERL_No的索引,避免了多个条件并列时优化器采用全表扫描的情况,于是优化后的SQL执行限制在10s内


目录
相关文章
|
4月前
|
存储 SQL 关系型数据库
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
|
7月前
|
SQL 存储 关系型数据库
SQL优化策略与实践:组合索引与最左前缀原则详解
本文介绍了SQL优化的多种方式,包括优化查询语句(避免使用SELECT *、减少数据处理量)、使用索引(创建合适索引类型)、查询缓存、优化表结构、使用存储过程和触发器、批量处理以及分析和监控数据库性能。同时,文章详细讲解了组合索引的概念及其最左前缀原则,即MySQL从索引的最左列开始匹配条件,若跳过最左列,则索引失效。通过示例代码,展示了如何在实际场景中应用这些优化策略,以提高数据库查询效率和系统响应速度。
290 10
|
8月前
|
SQL 索引
【YashanDB知识库】字段加上索引后,SQL查询不到结果
【YashanDB知识库】字段加上索引后,SQL查询不到结果
|
9月前
|
SQL 关系型数据库 OLAP
云原生数据仓库AnalyticDB PostgreSQL同一个SQL可以实现向量索引、全文索引GIN、普通索引BTREE混合查询,简化业务实现逻辑、提升查询性能
本文档介绍了如何在AnalyticDB for PostgreSQL中创建表、向量索引及混合检索的实现步骤。主要内容包括:创建`articles`表并设置向量存储格式,创建ANN向量索引,为表增加`username`和`time`列,建立BTREE索引和GIN全文检索索引,并展示了查询结果。参考文档提供了详细的SQL语句和配置说明。
280 2
|
SQL Oracle 关系型数据库
SQL优化-使用联合索引和函数索引
在一次例行巡检中,发现一条使用 `to_char` 函数将日期转换为字符串的 SQL 语句 CPU 利用率很高。为了优化该语句,首先分析了 where 条件中各列的选择性,并创建了不同类型的索引,包括普通索引、函数索引和虚拟列索引。通过对比不同索引的执行计划,最终确定了使用复合索引(包含函数表达式)能够显著降低查询成本,提高执行效率。
208 3
|
SQL 关系型数据库 MySQL
如何确认SQL用了索引:详细技巧与方法
在数据库管理中,索引是提高SQL查询性能的重要手段
2270 5
|
SQL 存储 关系型数据库
SQL默认索引是什么:深入解析与技巧
在SQL数据库中,索引是一种用于提高查询性能的重要数据结构
|
SQL 存储 关系型数据库
SQL默认索引是什么
在SQL数据库中,索引是一种用于提高查询性能的数据结构
|
SQL 关系型数据库 MySQL
如何确认SQL用了索引
在数据库管理和优化过程中,确认SQL查询是否使用了索引是一个至关重要的步骤
|
SQL 关系型数据库 MySQL
如何确认SQL查询是否使用了索引:详细步骤与技巧
在数据库管理和优化中,确认SQL查询是否有效利用了索引是提升性能的关键步骤
1330 0