转 sql 语句性能比较慢 执行计划

Dear :

该条SQL  主要慢在 如下 标黄线的 步骤 ,以下是 如下3表关联

3张表的总的 数据量在20200902 统计如下:

d0: 4860

d1 :581812893

d2:107189215

绑定变量值为20200901

select count(*) from aa.d1 GL  where  GL.RECORD_DATE = '20200901';

  COUNT(*)

----------

   1221920

SQL> select count(*) from aa.d0 where FDATE= '20200901';

  COUNT(*)

----------

         2

SQL>  select count(*) from aa.d2   where FDATE = '20200901';

  COUNT(*)

----------

     57968

当使用 MERGE JOIN CARTESIAN  时候,d1 中( 时间为'20200901' 的数据达到了1221920 )  和  d0( 时间为'20200901' 的数据达到了2 )进行笛卡尔查询,

没有使用关联条件,导致查询的返回结果 达到2500000 笔数据

  最后在跟d2 (时间为'20200901' 的数据达到了  57968)进行netloop 查询,导致数据库执行SQL 异常增加。

 

建议如下:

 

1.d1 表的字段 和 d0 的字段,做一个关联查询,,比如 d1.column_name = d0.column_name

2.找到更好的执行计划,固定执行计划,

附录:

Current Execution Plans (last execution)

Captured while still in memory. Metrics below are for the last execution of each child cursor.
If STATISTICS_LEVEL was set to ALL at the time of the hard-parse then A-Rows column is populated.

Inst: 1   Child: 0    Plan hash value: 3128636944

 

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

                      | Id  | Operation                               | Name                | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | Pstart| Pstop |  OMem |  1Mem | Used-Mem |

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

                      |   0 | INSERT STATEMENT                        |                     |        |       |   494 (100)|          |       |       |       |       |          |

                      |   1 |  LOAD TABLE CONVENTIONAL                |                     |        |       |            |          |       |       |       |       |          |

                      |   2 |   HASH GROUP BY                         |                     |      1 |   200 |   494   (1)| 00:00:06 |       |       |   762K|   762K|          |

                      |   3 |    NESTED LOOPS                         |                     |      1 |   200 |   493   (0)| 00:00:06 |       |       |       |       |          |

                      |   4 |     NESTED LOOPS                        |                     |      1 |   200 |   493   (0)| 00:00:06 |       |       |       |       |          |

                      |   5 |      MERGE JOIN CARTESIAN               |                     |      1 |   162 |   491   (0)| 00:00:06 |       |       |       |       |          |

                      |   6 |       PARTITION LIST SINGLE             |                     |      1 |   114 |     0   (0)|          |   KEY |   KEY |       |       |          |

                      |*  7 |        TABLE ACCESS BY LOCAL INDEX ROWID| d1             |      1 |   114 |     0   (0)|          |   KEY |   KEY |       |       |          |

                      |*  8 |         INDEX RANGE SCAN                | IDX_d1_02      |      1 |       |     0   (0)|          |   KEY |   KEY |       |       |          |

                      |   9 |       BUFFER SORT                       |                     |      2 |    96 |   491   (0)| 00:00:06 |       |       | 73728 | 73728 |          |

                     |* 10 |        TABLE ACCESS FULL                | d0 |      2 |    96 |   491   (0)| 00:00:06 |       |       |       |       |          |

                      |* 11 |      INDEX RANGE SCAN                   | IDX_d2_01 |  49057 |       |     1   (0)| 00:00:01 |       |       |       |       |          |

                      |* 12 |     TABLE ACCESS BY INDEX ROWID         | d2        |      1 |    38 |     2   (0)| 00:00:01 |       |       |       |       |          |

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

 

                      Query Block Name / Object Alias (identified by operation id):

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

 

SQL Text


INSERT INTO T096 (DATA_DATE, BRANCH, SEQ_NO, FLAG, PAY_dddd_NO, SHOU_dddd_NO, TRAN_AMT, TRAN_CNT) SELECT :B1 , GH.BRANCH, NULL, DECODE(GRA.IS_INTEREST, 'Y', 'L', 'B') FLAG, GRA.GL_dddd_NO, GRA.BASE_dddd_NO, ABS(SUM(DECODE(GH.REVERSAL, 'Y', DECODE(GH.DR_CR_IND, 'C', ABS(GH.AMOUNT), 'D', -1 * ABS(GH.AMOUNT)), 'N', DECODE(GH.DR_CR_IND, 'D', ABS(GH.AMOUNT), 'C', -1 * ABS(GH.AMOUNT))))), SUM(DECODE(GH.REVERSAL, 'N', 1, 'Y', -1)) CNT FROM d1 GH, d2 GAC, d0 GRA WHERE GH.dddd_INTERNAL_KEY = GAC.INTERNAL_KEY AND GAC.dddd_NO = GRA.GL_dddd_NO AND GH.SOURCE_TYPE = 'LO' AND GH.VALUE_DATE = GH.RECORD_DATE AND GH.RECORD_DATE = :B1 AND GH.FDATE = :B1 AND GAC.FDATE = :B1 AND GRA.FDATE = :B1 GROUP BY GRA.GL_dddd_NO, GH.BRANCH, DECODE(GRA.IS_INTEREST, 'Y', 'L', 'B'), GRA.BASE_dddd_NO

 

 

--分析过程

|* 7 | TABLE ACCESS BY LOCAL INDEX ROWID| d1| 1 | 114 | 0 (0)| | KEY | KEY | | | |
|* 8 | INDEX RANGE SCAN | IDX_GL_HIST_02 | 1 | | 0 (0)| | KEY | KEY | | | |
| 9 | BUFFER SORT | | 2 | 96 | 491 (0)| 00:00:06 | | | 73728 | 73728 | |
|* 10 | TABLE ACCESS FULL | d0 | 2 | 96 | 491 (0)| 00:00:06 | | | | |


7 - filter(("GH"."VALUE_DATE"=:B1 AND "GH"."RECORD_DATE"=:B1))
8 - access("GH"."FDATE"=:B1 AND "GH"."SOURCE_TYPE"='LO')
filter("GH"."SOURCE_TYPE"='LO')

10 - filter("GRA"."FDATE"=:B1)


d0: 4860

d1:581812893

d2:107189215

select count(*) from aa.d0;
select count(*) from aa.GL_HIST;
select count(*) from aa.d2;


select count(*) from aa.d1;

COUNT(*)
----------
595877133

SQL> select count(*) from aa.d2;

COUNT(*)
----------
107155579

SQL>
select count(*) from aa.d0;
COUNT(*)
----------
4952


select count(*) from aa.d1GL where GL.RECORD_DATE = '20200901';

COUNT(*)
----------
1221920

SQL> select count(*) from aa.d0 where FDATE= '20200901';

COUNT(*)
----------
2


SQL> select count(*) from aa.d2 where FDATE = '20200901';

COUNT(*)
----------
57968

SQL Text
--------------------------------------------------------------------------------

INSERT INTO TP_B_user096 (DATA_DATE, BRANCH, SEQ_NO, FLAG, PAY_dddd_NO, SHOU_dddd_NO, TRAN_AMT, TRAN_CNT) SELECT :B1 , GH.BRANCH, NULL, DECODE(GRA.IS_INTEREST, 'Y', 'L', 'B') FLAG, GRA.GL_dddd_NO, GRA.BASE_dddd_NO, ABS(SUM(DECODE(GH.REVERSAL, 'Y', DECODE(GH.DR_CR_IND, 'C', ABS(GH.AMOUNT), 'D', -1 * ABS(GH.AMOUNT)), 'N', DECODE(GH.DR_CR_IND, 'D', ABS(GH.AMOUNT), 'C', -1 * ABS(GH.AMOUNT))))), SUM(DECODE(GH.REVERSAL, 'N', 1, 'Y', -1)) CNT FROM d1GH, d2 GAC, d0 GRA WHERE GH.dddd_INTERNAL_KEY = GAC.INTERNAL_KEY AND GAC.dddd_NO = GRA.GL_dddd_NO AND GH.SOURCE_TYPE = 'LO' AND GH.VALUE_DATE = GH.RECORD_DATE AND GH.RECORD_DATE = :B1 AND GH.FDATE = :B1 AND GAC.FDATE = :B1 AND GRA.FDATE = :B1 GROUP BY GRA.GL_dddd_NO, GH.BRANCH, DECODE(GRA.IS_INTEREST, 'Y', 'L', 'B'), GRA.BASE_dddd_NO


假设绑定变量值为20200901

SQL> select count(*) from aa.d1GL w here GL.RECORD_DATE = '20200901';

COUNT(*)
----------
1221920


##查看正在执行的SQL 绑定变量值,
###https://www.cnblogs.com/kerrycode/p/7476443.html

sql_id:dp7mzr2kg3c4z

SELECT
b.sql_id,
t.sql_text sql_text,
b.name bind_name,
b.value_string bind_value
FROM
v$sql t
JOIN
v$sql_bind_capture b on t.hash_value = b.hash_value and t.child_address = b.child_address
WHERE
b.value_string is not null
AND
b.sql_id='&sqlid'


SQL> COL NAME FOR A12;
SQL> COL DATATYPE_STRING FOR A24;
SQL> COL VALUE_STRING FOR A32;
SQL> SELECT NAME,
2 DATATYPE_STRING,
3 VALUE_STRING,
4 MAX_LENGTH,
5 LAST_CAPTURED
6 FROM V$SQL_BIND_CAPTURE
7 WHERE SQL_ID = '1t2r2p48W4P0g';

后记:

--因为是insert 慢,后继  开发反馈单独select 查询很快,于是单独拿出select 看了看

发现走的快的执行计划还是跟慢的执行计划不一样,一个用的是IDX_GL_ACCT_CORE_02。一个用的是IDX_GL_ACCT_CORE_01

Plan hash value: 4260575868

---------------------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 0 |00:00:02.33 | 683K| | | |
| 1 | HASH GROUP BY | | 1 | 1 | 0 |00:00:02.33 | 683K| 762K| 762K| |
| 2 | NESTED LOOPS | | 1 | 1 | 0 |00:00:02.33 | 683K| | | |
| 3 | NESTED LOOPS | | 1 | 1 | 619K|00:00:02.50 | 64200 | | | |
| 4 | MERGE JOIN CARTESIAN | | 1 | 1 | 619K|00:00:01.57 | 64182 | | | |
| 5 | PARTITION LIST SINGLE | | 1 | 1 | 309K|00:00:00.62 | 63303 | | | |
|* 6 | TABLE ACCESS BY LOCAL INDEX ROWID| GL_HIST | 1 | 1 | 309K|00:00:00.58 | 63303 | | | |
|* 7 | INDEX RANGE SCAN | IDX_GL_HIST_02 | 1 | 1 | 309K|00:00:00.18 | 9536 | | | |
| 8 | BUFFER SORT | | 309K| 2 | 619K|00:00:00.14 | 879 | 2048 | 2048 | 2048 (0)|
|* 9 | TABLE ACCESS FULL | GL_RB_ACCT_TRANSFER | 1 | 2 | 2 |00:00:00.01 | 879 | | | |

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------
|* 10 | INDEX RANGE SCAN | IDX_GL_ACCT_CORE_02 | 619K| 1 | 619K|00:00:00.73 | 18 | | | |                                                 《-  这里走的是IDX_GL_ACCT_CORE_02
|* 11 | TABLE ACCESS BY INDEX ROWID | GL_ACCT_CORE | 619K| 1 | 0 |00:00:00.49 | 619K| | | |
---------------------------------------------------------------------------------------------------------------------------------------------------

验证如下: 强制走 索引 IDX_GL_ACCT_CORE_01 很慢

SELECT /*+ INDEX (GAC IDX_GL_ACCT_CORE_01 )*/
'20200902',
GH.BRANCH,
NULL,
DECODE(GRA.IS_INTEREST, 'Y', 'L', 'B') FLAG,
GRA.GL_ACCT_NO,

强制走索引 IDX_GL_ACCT_CORE_02  很快, 

SELECT /*+ INDEX (GAC IDX_GL_ACCT_CORE_02 )*/
'20200902',
GH.BRANCH,

这也给我们调优提供了一个思路,强制走索引 IDX_GL_ACCT_CORE_02   也是一条优化建议。 

通过这个案例,感觉到O 记的自适应性,和社区的强大。这一点远远超过 开源数据库 社区。

原文地址:https://www.cnblogs.com/feiyun8616/p/13600673.html