【发布时间】:2017-12-20 09:00:36
【问题描述】:
我的生产环境中有以下查询
SELECT CIF,
DECODE( 'INFENG' , '' ,NVL(ALT1_NAME,NAME),NAME),
DECODE( 'INFENG' , '' ,NVL(ALT1_SHORT_NAME,SHORT_NAME),SHORT_NAME),
CORP_ID
FROM tb.CMG ,
tb.SST
WHERE SST.BANK_ID = '54'
AND CMG.PRIMARY_SOL_ID = SST.SOL_ID
AND SST.SET_ID = '000'
AND CMG.BANK_ID = '54'
AND CMG.ENTITY_CRE_FLG = 'Y'
AND EXISTS
(SELECT 1
FROM tb.CPHONE
WHERE CPHONE.PHONE_B2KID = CMG.CIF_ID
AND PHONENO LIKE '%4444%'
)
AND CORP_ID IS NULL
AND ROWNUM < 801
ORDER BY 4
给出结果需要超过 5 分钟。查询的解释计划是
Plan hash value: 4143484456
--------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 207 | 9732 (1)| 00:00:01 |
| 1 | SORT ORDER BY | | 1 | 207 | 9732 (1)| 00:00:01 |
|* 2 | COUNT STOPKEY | | | | | |
|* 3 | FILTER | | | | | |
| 4 | NESTED LOOPS | | 4325 | 874K| 5297 (1)| 00:00:01 |
| 5 | NESTED LOOPS | | 44112 | 874K| 5297 (1)| 00:00:01 |
|* 6 | INDEX RANGE SCAN | IDX_SOL_ID_SET_TABLE | 1 | 16 | 1 (0)| 00:00:01 |
|* 7 | INDEX RANGE SCAN | IX_ACCOUNTS_PSOLID | 44112 | | 1 (0)| 00:00:01 |
|* 8 | TABLE ACCESS BY INDEX ROWID | ACCOUNTS | 4325 | 806K| 5296 (1)| 00:00:01 |
| 9 | NESTED LOOPS SEMI NA | | 1 | 92 | 2 (0)| 00:00:01 |
|* 10 | TABLE ACCESS BY INDEX ROWID BATCHED| PHONEEMAIL | 1 | 83 | 1 (0)| 00:00:01 |
|* 11 | INDEX RANGE SCAN | IX_ORGKEY_PHONEEMAILTYPE | 3 | | 1 (0)| 00:00:01 |
|* 12 | TABLE ACCESS BY INDEX ROWID BATCHED| NON_CUSTOMERS | 1 | 9 | 1 (0)| 00:00:01 |
|* 13 | INDEX RANGE SCAN | PK322 | 1 | | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(ROWNUM<801)
3 - filter( EXISTS (SELECT /*+ <not feasible>)
6 - access("SST"."SET_ID"='000' AND "SST"."BANK_ID"='54')
filter("SST"."BANK_ID"='54')
7 - access("ACCOUNTS"."PRIMARY_SOL_ID"=SYS_OP_C2C("SOL_ID") AND "ACCOUNTS"."BANK_ID"=U'54')
8 - filter("ACCOUNTS"."ENTITY_CRE_FLAG"=U'Y' AND "ACCOUNTS"."CORP_ID" IS NULL)
10 - filter("PHONEEMAIL"."PHONEOREMAIL"=U'PHONE' AND SUBSTR("PHONENO",1,20) LIKE U'%4444%' AND
SUBSTR("PHONENO",1,20) IS NOT NULL AND "SUSPECTID" IS NULL AND "CONTACTID" IS NULL)
11 - access("PHONEEMAIL"."ORGKEY"=:B1)
12 - filter("A"."CONVFLAG"=U'N' OR "A"."CONVFLAG" IS NULL)
13 - access("A"."NONCUSTOMERID"="PHONEEMAIL"."NONCUSTOMERID")
Note
-----
- dynamic statistics used: dynamic sampling (level=1)
- this is an adaptive plan
- 1 Sql Plan Directive used for this statement
谁能告诉我如何优化这个查询以减少执行时间。
我在测试数据库中有相同的日期,查询时间不到一分钟。那里有解释计划
Plan hash value: 888087711
----------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 296 | 15491 (7)| 00:00:01 |
| 1 | SORT UNIQUE | | 1 | 296 | 15490 (7)| 00:00:01 |
|* 2 | COUNT STOPKEY | | | | | |
| 3 | NESTED LOOPS | | 1 | 296 | 15489 (7)| 00:00:01 |
| 4 | NESTED LOOPS | | 1 | 283 | 15488 (7)| 00:00:01 |
|* 5 | HASH JOIN RIGHT SEMI NA | | 1 | 92 | 15487 (7)| 00:00:01 |
|* 6 | TABLE ACCESS STORAGE FULL | NON_CUSTOMERS | 9 | 81 | 2 (0)| 00:00:01 |
|* 7 | TABLE ACCESS STORAGE FULL | PHONEEMAIL | 783K| 62M| 15482 (7)| 00:00:01 |
|* 8 | TABLE ACCESS BY INDEX ROWID BATCHED| ACCOUNTS | 1 | 191 | 1 (0)| 00:00:01 |
|* 9 | INDEX RANGE SCAN | IX_ACCOUNTS_ORGKEY | 1 | | 1 (0)| 00:00:01 |
|* 10 | INDEX RANGE SCAN | IDX_SOL_ID_SET_TABLE | 1 | 13 | 1 (0)| 00:00:01 |
----------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(ROWNUM<801)
5 - access("A"."NONCUSTOMERID"="PHONEEMAIL"."NONCUSTOMERID")
6 - storage("A"."CONVFLAG"=U'N' OR "A"."CONVFLAG" IS NULL)
filter("A"."CONVFLAG"=U'N' OR "A"."CONVFLAG" IS NULL)
7 - storage("PHONEEMAIL"."PHONEOREMAIL"=U'PHONE')
filter("PHONEEMAIL"."PHONEOREMAIL"=U'PHONE' AND SUBSTR("PHONENO",1,20) LIKE U'%4444%' AND
SUBSTR("PHONENO",1,20) IS NOT NULL AND "SUSPECTID" IS NULL AND "CONTACTID" IS NULL)
8 - filter("ACCOUNTS"."ENTITY_CRE_FLAG"=U'Y' AND "ACCOUNTS"."CORP_ID" IS NULL)
9 - access("PHONEEMAIL"."ORGKEY"="ACCOUNTS"."ORGKEY" AND "ACCOUNTS"."BANK_ID"=U'54')
10 - access("SST"."SET_ID"='000' AND "SST"."BANK_ID"='54')
filter("SST"."BANK_ID"='54' AND "ACCOUNTS"."PRIMARY_SOL_ID"=SYS_OP_C2C("SST"."SOL_ID"))
Note
-----
- dynamic statistics used: dynamic sampling (level=1)
- this is an adaptive plan
- 2 Sql Plan Directives used for this statement
【问题讨论】:
-
这对于 dba 交换会更好:dba.stackexchange.com
-
CMG.PRIMARY_SOL_ID和SST.SOL_ID列的数据类型是什么。希望其中之一是NVARCHAR(),导致隐式转换调用SYS_OP_C2C(),抑制索引的使用。 -
@MaheswaranRavisankar cmg.primary_sol_id 是 NVARCHAR2 而 sst.sol_id 是 VARCHAR2
-
太好了,这可能是罪魁祸首,您可能想在该列上添加一个基于函数的索引,例如
to_nchar(CMG.PRIMARY_SOL_ID)。或者匹配这些列的数据类型。 More details here -
解释计划显示总执行时间(估计)为一秒。那是怎么回事?你能生成一个实际的执行计划并分享吗?然后 - 如果优化器认为它会在一秒钟内完成所有事情,那么您的统计数据可能已经过时了。他们是吗?而且,为什么解释计划显示 SELECT 语句将只返回一行而不是 800? 或...您发布的查询中的计划不是真的吗?太多东西看起来不一样了。
标签: oracle database-performance oracle12c