oracle

推荐列表 站点导航

当前位置:首页 > 数据库 > oracle >

解析一个通过添加本地分区索引提高SQL性能的案例

来源:网络整理  作者:网络  发布时间:2020-12-11 19:23
今天接到同事求助,说有一个select query,在Oracle上要跑一分多钟,他希望能在5s内出结果,以下就是解决这个问题的方...
  And Src.Systemname = Rl.Systemname

复制代码 代码如下:

  And Not(
 inner <STRONG>join DR_QRY_LOG_EXP_HST</STRONG> rl on
  15 - filter("SRC"."ACCTSTRINGDATE"="TGT"."ACCTSTRINGDATE" AND (UPPER("TGT"."SYSTEMNAME")<>UPPER("SRC"."SYSTEMNAME") OR
    Upper(Tgt.Databasename) = Upper(Src.Databasename)
  And Upper(tgt.Tablename) = Upper('SSA_SLNG_LSTG_MTRC_SD')
  And   tgt.tablename is not null

              "TGT"."DATABASENAME" IS NOT NULL AND "TGT"."TABLENAME" IS NOT NULL)
  upper(tgt.systemname) = upper('MOZART')

复制代码 代码如下:

    And
  and rl.statement_id = tgt.statement_id</STRONG>
定位问题

|   1 |  PX COORDINATOR                        |                               |       |       |       |       |       |
    Upper(Tgt.Tablename) = Upper(Src.Tablename)
------------------------------------------------------------------------------------------------------------------------
  and src.queryid = rl.queryid</STRONG>
从上面执行计划中的表连接方式可以知道,这三个表之间进行了两次NESTED LOOP,问题出现在最里层的NESTED LOOP(对两个表都做了TABLE FULL SCAN),因为表都是百万级别的(即时过滤后的数据量也不小),性能问题就出现在内表(即被驱动表)META_DBQL_TABLE_USAGE_EXP_HST做了太多次的全表扫描。如果能把全表扫描转换成索引,则性能可以大幅度提高。

Predicate Information (identified by operation id):
|   9 |          BUFFER SORT                   |                               |       |       |       |       |       |
              UPPER("TGT"."TABLENAME")='SSA_SLNG_LSTG_MTRC_SD' AND "TGT"."ACCTSTRINGDATE">SYSDATE@!-30 AND "TGT"."SYSTEMNAME" IS NOT NULL
|   2 |   PX SEND QC (RANDOM)                  | :TQ10002                      |     1 |   159 |  8654 |       |       |
  And Upper(tgt.Databasename) = Upper('GDW_TABLES')


|  11 |            PX SEND BROADCAST           | :TQ10000                      |       |       |       |       |       |
------------------------------------------------------------------------------------------------------------------------
  src.systemname as systemname
       filter("RL"."ACCTSTRINGDATE">SYSDATE@!-30)

复制代码 代码如下:

  and src.acctstringdate > sysdate - 30
  And   tgt.Databasename Is Not Null
下面是这三个表上索引的情况:
|  16 |         PARTITION RANGE ITERATOR       |                               |     1 |       |     2 |   KEY |   KEY |
  And   tgt.Systemname is not null
  13 - filter(UPPER("TGT"."SYSTEMNAME")='MOZART' AND UPPER("TGT"."DATABASENAME")='GDW_TABLES' AND
|* 15 |           TABLE ACCESS FULL            | META_DBQL_TABLE_USAGE_EXP_HST |  8959 |   586K|   154 |   KEY |   KEY |
              "SRC"."ACCTSTRINGDATE">SYSDATE@!-30)
------------------------------------------------------------------------------------------------------------------------
  And Tgt.Acctstringdate > Sysdate - 30
  ,  src.tablename as tablename
|   0 | SELECT STATEMENT                       |                               |     1 |   159 |  8654 |       |       |
|*  6 |       TABLE ACCESS BY LOCAL INDEX ROWID| DR_QRY_LOG_EXP_HST            |     1 |    36 |     3 |       |       |
|  14 |          PX BLOCK ITERATOR             |                               |  8959 |   586K|   154 |   KEY |   KEY |
总得来看,这个SQL就是三个表(meta_dbql_table_usage_exp_hst,DR_QRY_LOG_EXP_HST,meta_dr_qry_log_tgt_all_hst)的INNER JOIN,这三个表数据量都在百万级别,且都是分区表(以acctstringdate为分区键),执行计划如下:
|   8 |         NESTED LOOPS                   |                               |  8959 |  1076K|  4900 |       |       |
|  10 |           PX RECEIVE                   |                               |       |       |       |       |       |
 inner join  <STRONG>meta_dr_qry_log_tgt_all_hst </STRONG>tgt on
嵌套连接把要处理的数据集分为外部循环(驱动数据源)和内部循环(被驱动数据源),外部循环只执行一次,内部循环执行的次数等于外部循环执行返回的数据个数。
SQL的简单分析
  <STRONG>AND src.acctstringdate = tgt.acctstringdate
  <STRONG>src.acctstringdate = rl.acctstringdate
              UPPER("TGT"."DATABASENAME")<>UPPER("SRC"."DATABASENAME") OR UPPER("TGT"."TABLENAME")<>UPPER("SRC"."TABLENAME")) AND
    Upper(Tgt.Systemname)=Upper(src.systemname)
|   7 |        NESTED LOOPS                    |                               |     1 |   159 |  8633 |       |       |
|  12 |             PARTITION RANGE ITERATOR   |                               |     1 |    56 |  4746 |   KEY |    14 |
    And
---------------------------------------------------
   6 - filter("RL"."STATEMENT_ID"="TGT"."STATEMENT_ID" AND "RL"."SYSTEMNAME"="TGT"."SYSTEMNAME" AND "SRC"."SYSTEMNAME"="RL"."SYSTEMNAME")
Select  /*+ parallel(src, 8) */ distinct

|   3 |    SORT UNIQUE                         |                               |     1 |   159 |  8654 |       |       |
  ,  src.username as username

  17 - access("SRC"."QUERYID"="RL"."QUERYID" AND "SRC"."ACCTSTRINGDATE"="RL"."ACCTSTRINGDATE")
| Id  | Operation                              | Name                          | Rows  | Bytes | Cost  | Pstart| Pstop |
如果驱动数据源有限,且被驱动表在连接列上有相应的索引,则这种连接方式才是高效的。

    )
from  <STRONG>meta_dbql_table_usage_exp_hst</STRONG> src
|* 17 |          INDEX RANGE SCAN              | DR_QRY_LOG_EXP_HST_IDX        |     1 |       |     2 |   KEY |   KEY |
  And Rl.Acctstringdate > Sysdate - 30
|   4 |     PX RECEIVE                         |                               |     1 |    36 |     3 |       |       |


  ,  src.databasename as databasename
|* 13 |              TABLE ACCESS FULL         | META_DR_QRY_LOG_TGT_ALL_HST   |     1 |    56 |  4746 |   KEY |    14 |

下面是NESTED LOOP的介绍:
|   5 |      PX SEND HASH                      | :TQ10001                      |     1 |    36 |     3 |       |       |
  and rl.systemname = tgt.systemname
这种连接的好处是内存使用非常少。

相关热词: 解析

本站内容来源于网络,如有侵权请与我们联系,我们会及时删除,我们深感抱歉!
注:本站所有信息仅供用于网络技术学习参考,学习中请遵循相关法律法规!

本文地址: https://v30.fanwenzhu.com/sql/oracle/2657.shtml

Copyright © www.juheyunku.com      关于 | 合作 | 声明 | 联系 | 更新 | 地图 | Tags

解析一个通过添加本地分区索引提高SQL性能的案例

2020-12-11 编辑:网络

  And Src.Systemname = Rl.Systemname

复制代码 代码如下:

  And Not(
 inner <STRONG>join DR_QRY_LOG_EXP_HST</STRONG> rl on
  15 - filter("SRC"."ACCTSTRINGDATE"="TGT"."ACCTSTRINGDATE" AND (UPPER("TGT"."SYSTEMNAME")<>UPPER("SRC"."SYSTEMNAME") OR
    Upper(Tgt.Databasename) = Upper(Src.Databasename)
  And Upper(tgt.Tablename) = Upper('SSA_SLNG_LSTG_MTRC_SD')
  And   tgt.tablename is not null

              "TGT"."DATABASENAME" IS NOT NULL AND "TGT"."TABLENAME" IS NOT NULL)
  upper(tgt.systemname) = upper('MOZART')

复制代码 代码如下:

    And
  and rl.statement_id = tgt.statement_id</STRONG>
定位问题

|   1 |  PX COORDINATOR                        |                               |       |       |       |       |       |
    Upper(Tgt.Tablename) = Upper(Src.Tablename)
------------------------------------------------------------------------------------------------------------------------
  and src.queryid = rl.queryid</STRONG>
从上面执行计划中的表连接方式可以知道,这三个表之间进行了两次NESTED LOOP,问题出现在最里层的NESTED LOOP(对两个表都做了TABLE FULL SCAN),因为表都是百万级别的(即时过滤后的数据量也不小),性能问题就出现在内表(即被驱动表)META_DBQL_TABLE_USAGE_EXP_HST做了太多次的全表扫描。如果能把全表扫描转换成索引,则性能可以大幅度提高。

Predicate Information (identified by operation id):
|   9 |          BUFFER SORT                   |                               |       |       |       |       |       |
              UPPER("TGT"."TABLENAME")='SSA_SLNG_LSTG_MTRC_SD' AND "TGT"."ACCTSTRINGDATE">SYSDATE@!-30 AND "TGT"."SYSTEMNAME" IS NOT NULL
|   2 |   PX SEND QC (RANDOM)                  | :TQ10002                      |     1 |   159 |  8654 |       |       |
  And Upper(tgt.Databasename) = Upper('GDW_TABLES')


|  11 |            PX SEND BROADCAST           | :TQ10000                      |       |       |       |       |       |
------------------------------------------------------------------------------------------------------------------------
  src.systemname as systemname
       filter("RL"."ACCTSTRINGDATE">SYSDATE@!-30)

复制代码 代码如下:

  and src.acctstringdate > sysdate - 30
  And   tgt.Databasename Is Not Null
下面是这三个表上索引的情况:
|  16 |         PARTITION RANGE ITERATOR       |                               |     1 |       |     2 |   KEY |   KEY |
  And   tgt.Systemname is not null
  13 - filter(UPPER("TGT"."SYSTEMNAME")='MOZART' AND UPPER("TGT"."DATABASENAME")='GDW_TABLES' AND
|* 15 |           TABLE ACCESS FULL            | META_DBQL_TABLE_USAGE_EXP_HST |  8959 |   586K|   154 |   KEY |   KEY |
              "SRC"."ACCTSTRINGDATE">SYSDATE@!-30)
------------------------------------------------------------------------------------------------------------------------
  And Tgt.Acctstringdate > Sysdate - 30
  ,  src.tablename as tablename
|   0 | SELECT STATEMENT                       |                               |     1 |   159 |  8654 |       |       |
|*  6 |       TABLE ACCESS BY LOCAL INDEX ROWID| DR_QRY_LOG_EXP_HST            |     1 |    36 |     3 |       |       |
|  14 |          PX BLOCK ITERATOR             |                               |  8959 |   586K|   154 |   KEY |   KEY |
总得来看,这个SQL就是三个表(meta_dbql_table_usage_exp_hst,DR_QRY_LOG_EXP_HST,meta_dr_qry_log_tgt_all_hst)的INNER JOIN,这三个表数据量都在百万级别,且都是分区表(以acctstringdate为分区键),执行计划如下:
|   8 |         NESTED LOOPS                   |                               |  8959 |  1076K|  4900 |       |       |
|  10 |           PX RECEIVE                   |                               |       |       |       |       |       |
 inner join  <STRONG>meta_dr_qry_log_tgt_all_hst </STRONG>tgt on
嵌套连接把要处理的数据集分为外部循环(驱动数据源)和内部循环(被驱动数据源),外部循环只执行一次,内部循环执行的次数等于外部循环执行返回的数据个数。
SQL的简单分析
  <STRONG>AND src.acctstringdate = tgt.acctstringdate
  <STRONG>src.acctstringdate = rl.acctstringdate
              UPPER("TGT"."DATABASENAME")<>UPPER("SRC"."DATABASENAME") OR UPPER("TGT"."TABLENAME")<>UPPER("SRC"."TABLENAME")) AND
    Upper(Tgt.Systemname)=Upper(src.systemname)
|   7 |        NESTED LOOPS                    |                               |     1 |   159 |  8633 |       |       |
|  12 |             PARTITION RANGE ITERATOR   |                               |     1 |    56 |  4746 |   KEY |    14 |
    And
---------------------------------------------------
   6 - filter("RL"."STATEMENT_ID"="TGT"."STATEMENT_ID" AND "RL"."SYSTEMNAME"="TGT"."SYSTEMNAME" AND "SRC"."SYSTEMNAME"="RL"."SYSTEMNAME")
Select  /*+ parallel(src, 8) */ distinct

|   3 |    SORT UNIQUE                         |                               |     1 |   159 |  8654 |       |       |
  ,  src.username as username

  17 - access("SRC"."QUERYID"="RL"."QUERYID" AND "SRC"."ACCTSTRINGDATE"="RL"."ACCTSTRINGDATE")
| Id  | Operation                              | Name                          | Rows  | Bytes | Cost  | Pstart| Pstop |
如果驱动数据源有限,且被驱动表在连接列上有相应的索引,则这种连接方式才是高效的。

    )
from  <STRONG>meta_dbql_table_usage_exp_hst</STRONG> src
|* 17 |          INDEX RANGE SCAN              | DR_QRY_LOG_EXP_HST_IDX        |     1 |       |     2 |   KEY |   KEY |
  And Rl.Acctstringdate > Sysdate - 30
|   4 |     PX RECEIVE                         |                               |     1 |    36 |     3 |       |       |


  ,  src.databasename as databasename
|* 13 |              TABLE ACCESS FULL         | META_DR_QRY_LOG_TGT_ALL_HST   |     1 |    56 |  4746 |   KEY |    14 |

下面是NESTED LOOP的介绍:
|   5 |      PX SEND HASH                      | :TQ10001                      |     1 |    36 |     3 |       |       |
  and rl.systemname = tgt.systemname
这种连接的好处是内存使用非常少。

本站内容来源于网络,如有侵权请与我们联系,我们会及时删除,我们深感抱歉!
注:本站所有信息仅供学习参考!
本文地址为 https://v30.fanwenzhu.com/sql/oracle/2657.shtml

相关文章

风云图片

推荐阅读

返回oracle频道首页