[英]how to do SQL tuning on below update sql
大家,最近我參與了一個oracle的SQL調優任務,我遇到了一個我認為非常困難的問題,我什至可以說我被這個問題嚇到了,我從DBA那里得到了AWR報告,並且似乎是來自AMR的紅線SQL需要做一些調整(我已經將這些SQL粘貼如下,這個sql在SP中)。但我不知道是什么原因導致性能不佳,任何人都可以幫助提供一些解決方案或調整SQL的想法?
如果您需要 AWR 的更多證據,請告訴我。
提前致謝...
UPDATE tax_ratio tar
SET
( ecm,
esm,
epm,
ecam,
update_dt,
update_by ) = (
SELECT
nvl(src_t1.ecm,0) AS ecm,
nvl(src_t1.esm,0) AS esm,
nvl(src_t1.epm,0) AS epm,
nvl(src_t1.ecam,0) AS ecam,
SYSDATE,
'ffee_user'
FROM
(
SELECT
city_code,
tax_type,
company_type,
taxpayer,
company_group,
company_tax_type,
SUM(new_tax_current_mth) /12 AS ecm,
SUM(new_tax_miss_current_mth) /12 AS esm,
SUM(new_tax_get_current_mth) /12 AS epm,
SUM(new_tax_special_current_mth) /12 AS ecam
FROM
tax_ratio
WHERE
city_code ='001'
AND company_type ='typ_01'
AND tax_mth <= add_months(TO_DATE('08-JUL-2015'),-3)
AND tax_mth >= add_months(TO_DATE('08-JUL-2015'),-14)
AND eff_date =TO_DATE('08-JUL-2015')
AND tax_type = '00'
GROUP BY
city_code,
tax_type,
company_type,
taxpayer,
company_group,
company_tax_type
HAVING SUM(new_tax_current_mth) <> 0
OR SUM(new_tax_miss_current_mth) <> 0
OR SUM(new_tax_get_current_mth) <> 0
OR SUM(new_tax_special_current_mth) <> 0
) src_t1
WHERE
tar.city_code = src_t1.city_code
AND tar.tax_type = src_t1.tax_type
AND tar.company_type = src_t1.company_type
AND tar.taxpayer = src_t1.taxpayer
AND nvl(tar.company_group,'-99999') = nvl(src_t1.company_group,'-99999')
AND (
src_t1.ecm IS NOT NULL
OR src_t1.esm IS NOT NULL
OR src_t1.epm IS NOT NULL
OR src_t1.ecam IS NOT NULL
)
AND tar.tax_mth =TO_DATE('08-JUL-2015')
AND tar.company_tax_type = src_t1.company_tax_type
)
WHERE
tar.city_code ='001'
AND tar.company_type ='typ_01'
AND tar.tax_mth =TO_DATE('08-JUL-2015')
AND EXISTS (
SELECT
1
FROM
(
SELECT
city_code,
tax_type,
company_type,
taxpayer,
company_group,
company_tax_type,
SUM(new_tax_current_mth) /12 AS ecm,
SUM(new_tax_miss_current_mth) /12 AS esm,
SUM(new_tax_get_current_mth) /12 AS epm,
SUM(new_tax_special_current_mth) /12 AS ecam
FROM
tax_ratio
WHERE
city_code ='001'
AND company_type ='typ_01'
AND tax_mth <= add_months(TO_DATE('08-JUL-2015'),-3)
AND tax_mth >= add_months(TO_DATE('08-JUL-2015'),-14)
AND eff_date =TO_DATE('08-Aug-2015')
AND tax_type = '00'
GROUP BY
city_code,
tax_type,
company_type,
taxpayer,
company_group,
company_tax_type
HAVING SUM(new_tax_current_mth) <> 0
OR SUM(new_tax_miss_current_mth) <> 0
OR SUM(new_tax_get_current_mth) <> 0
OR SUM(new_tax_special_current_mth) <> 0
) src_t1
WHERE
tar.city_code = src_t1.city_code
AND tar.tax_type = src_t1.tax_type
AND tar.company_type = src_t1.company_type
AND tar.taxpayer = src_t1.taxpayer
AND nvl(tar.company_group,'-99999') = nvl(src_t1.company_group,'-99999')
AND (
src_t1.ecm IS NOT NULL
OR src_t1.esm IS NOT NULL
OR src_t1.epm IS NOT NULL
OR src_t1.ecam IS NOT NULL
)
AND tar.tax_mth =TO_DATE('08-JUL-2015')
AND tar.company_tax_type = src_t1.company_tax_type
)
add the EXPLAIN PLAN
PLAN HASH VALUE: 3650439649
----------------------------------------------------------------------------------------------------------------------
| ID | OPERATION | NAME | ROWS | BYTES |TEMPSPC| COST (%CPU)| TIME |
----------------------------------------------------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 1698 | 179K| | 6169K (1)| 00:08:02 |
| 1 | UPDATE | TAX_RATIO | | | | | |
|* 2 | HASH JOIN RIGHT SEMI | | 1698 | 179K| | 732K (1)| 00:00:58 |
| 3 | VIEW | | 39251 | 1111K| | 371K (2)| 00:00:29 |
|* 4 | FILTER | | | | | | |
| 5 | SORT GROUP BY | | 39251 | 2414K| 100M| 371K (2)| 00:00:29 |
|* 6 | TABLE ACCESS FULL | TAX_RATIO | 1140K| 68M| | 365K (2)| 00:00:29 |
|* 7 | TABLE ACCESS FULL | TAX_RATIO | 207K| 15M| | 361K (1)| 00:00:29 |
| 8 | VIEW | | 1 | 81 | | 484 (1)| 00:00:01 |
|* 9 | FILTER | | | | | | |
| 10 | SORT GROUP BY | | 1 | 63 | | 484 (1)| 00:00:01 |
|* 11 | FILTER | | | | | | |
|* 12 | TABLE ACCESS BY INDEX ROWID BATCHED| TAX_RATIO | 1 | 63 | | 483 (0)| 00:00:01 |
|* 13 | INDEX RANGE SCAN | TAX_RATIO_TAXPAYER_IDX | 544 | | | 3 (0)| 00:00:01 |
----------------------------------------------------------------------------------------------------------------------
PREDICATE INFORMATION (IDENTIFIED BY OPERATION ID):
---------------------------------------------------
2 - ACCESS("TAR"."CITY_CODE"="SRC_T1"."CITY_CODE" AND "TAR"."TAX_TYPE"="SRC_T1"."TAX_TYPE" AND
"TAR"."COMPANY_TYPE"="SRC_T1"."COMPANY_TYPE" AND "TAR"."TAXPAYER"="SRC_T1"."TAXPAYER" AND
NVL("TAR"."COMPANY_GROUP",'-99999')=NVL("SRC_T1"."COMPANY_GROUP",'-99999') AND "TAR"."COMPANY_TAX_TYPE"="SRC_T1"."COMPANY_TAX_TYPE")
4 - FILTER((SUM("NEW_TAX_CURRENT_MTH")<>0 OR SUM("NEW_TAX_MISS_CURRENT_MTH")<>0 OR SUM("NEW_TAX_GET_CURRENT_MTH")<>0 OR SUM("NEW_TAX_SPECIAL_CURRENT_MTH")<>0) AND
(SUM("NEW_TAX_CURRENT_MTH")/12 IS NOT NULL OR SUM("NEW_TAX_MISS_CURRENT_MTH")/12 IS NOT NULL OR SUM("NEW_TAX_GET_CURRENT_MTH")/12 IS NOT NULL OR
SUM("NEW_TAX_SPECIAL_CURRENT_MTH")/12 IS NOT NULL))
6 - FILTER("COMPANY_TYPE"='LIMIT' AND "TAX_TYPE"='00' AND "TAX_MTH">=TO_DATE(' 2017-03-31 00:00:00',
'SYYYY-MM-DD HH24:MI:SS') AND "TAX_MTH"<=TO_DATE(' 2018-02-28 00:00:00', 'SYYYY-MM-DD HH24:MI:SS') AND
"CITY_CODE"='001' AND "NEW_TAX_MISS_CURRENT_MTH"=TO_DATE(' 2200-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS'))
7 - FILTER("TAR"."TAX_MTH"=TO_DATE(' 2018-05-31 00:00:00', 'SYYYY-MM-DD HH24:MI:SS') AND
"TAR"."COMPANY_TYPE"='LIMIT' AND "TAR"."CITY_CODE"='001')
9 - FILTER((SUM("NEW_TAX_CURRENT_MTH")<>0 OR SUM("NEW_TAX_MISS_CURRENT_MTH")<>0 OR SUM("NEW_TAX_GET_CURRENT_MTH")<>0 OR SUM("NEW_TAX_SPECIAL_CURRENT_MTH")<>0) AND
(SUM("NEW_TAX_CURRENT_MTH")/12 IS NOT NULL OR SUM("NEW_TAX_MISS_CURRENT_MTH")/12 IS NOT NULL OR SUM("NEW_TAX_GET_CURRENT_MTH")/12 IS NOT NULL OR
SUM("NEW_TAX_SPECIAL_CURRENT_MTH")/12 IS NOT NULL))
11 - FILTER(:B1=TO_DATE(' 2018-05-31 00:00:00', 'SYYYY-MM-DD HH24:MI:SS') AND :B2='LIMIT' AND :B3='00' AND
:B4='001')
12 - FILTER("COMPANY_TYPE"='LIMIT' AND "COMPANY_TAX_TYPE"=:B1 AND "TAX_TYPE"='00' AND "TAX_MTH">=TO_DATE('
2017-03-31 00:00:00', 'SYYYY-MM-DD HH24:MI:SS') AND "TAX_MTH"<=TO_DATE(' 2018-02-28 00:00:00', 'SYYYY-MM-DD
HH24:MI:SS') AND NVL("COMPANY_GROUP",'-99999')=NVL(:B2,'-99999') AND "CITY_CODE"='001' AND "NEW_TAX_MISS_CURRENT_MTH"=TO_DATE('
2200-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS'))
13 - ACCESS("TAXPAYER"=:B1)
我要嘗試的第一件事是使用 MERGE 語句而不是 UPDATE 語句 - 這讓我想到了,因為您實際上是在 where 子句中的 set 子句中重復子查詢。
我認為您的 UPDATE 可以重寫為:
MERGE INTO tax_ratio tgt
USING (SELECT city_code,
tax_type,
company_type,
taxpayer,
company_group,
company_tax_type,
SUM(new_tax_current_mth) / 12 AS ecm,
SUM(new_tax_miss_current_mth) / 12 AS esm,
SUM(new_tax_get_current_mth) / 12 AS epm,
SUM(new_tax_special_current_mth) / 12 AS ecam
FROM tax_ratio
WHERE city_code = '001'
AND company_type = 'typ_01'
AND tax_mth <= add_months(to_date('08-JUL-2015', 'dd-MON-yyyy', 'nls_date_language = english'), -3)
AND tax_mth >= add_months(to_date('08-JUL-2015', 'dd-MON-yyyy', 'nls_date_language = english'), -3)
AND eff_date = to_date('08-JUL-2015', 'dd-MON-yyyy', 'nls_date_language = english')
AND tax_type = '00'
GROUP BY city_code,
tax_type,
company_type,
taxpayer,
company_group,
company_tax_type
HAVING SUM(new_tax_current_mth) <> 0
OR SUM(new_tax_miss_current_mth) <> 0
OR SUM(new_tax_get_current_mth) <> 0
OR SUM(new_tax_special_current_mth) <> 0)) src
ON (tgt.city_code = src.city_code
AND tgt.tax_type = src.tax_type
AND tgt.company_type = src.company_type
AND tgt.taxpayer = src.taxpayer
AND NVL(tgt.company_group, '-99999') = NVL(src.company_group, '-99999')
--AND COALESCE(src.ecm, src.esm, src.epm, src.ecam) IS NOT NULL -- unnecessary, since your having clause excludes rows where all are null anyway
AND tgt.company_tax_type = src.company_tax_type)
WHEN MATCHED THEN
UPDATE SET tgt.ecm = NVL(src.ecm, 0),
tgt.esm = NVL(src.esm, 0),
tgt.epm = NVL(src.epm, 0),
tgt.ecam = NVL(src.ecam, 0),
tgt.update_dt = SYSDATE,
tgt.update_by = 'ffee_user')
WHERE tgt.tax_mth = to_date('08-JUL-2015', 'dd-MON-yyyy', 'nls_date_language = english');
筆記:
to_dates()
以包含格式掩碼(否則,如果您的 NLS_DATE_FORMAT nls 參數已更改,則to_date()
將失敗)並且,由於您使用“JUL”作為月份,因此附加的第三個參數用於制作日期-as-a-string 轉換 nls 設置獨立(例如,如果您的 NLS_DATE_FORMAT nls 參數設置為JUL
不是有效的短月,如果未設置第三個參數,則to_date()
將失敗)。 您可以通過將日期作為數字傳遞來避免使用第三個參數,例如to_date('05/07/2015', 'dd/mm/yyyy')
。and ecm is not null and esm is not null and...
改為使用COALESCE
,因為這會返回列表中的第一個非空值。 因此,您的支票變為and COALESCE(ecm, esm, ...) is not null
。我會測試新的 MERGE 語句以確保它正在做正確的事情(或修復它直到它做正確)然后看看它如何影響性能。
如果它仍然作為 AWR 中的問題陳述彈出,那么我將進一步研究如何調整它; 可能需要更新/附加索引,可能需要物化視圖等。
1.我會建議你在表級訪問大量數據的條件下創建索引。在索引上創建后。將節省時間
tax_ratio WHERE city_code ='001' AND company_type ='typ_01' AND tax_mth <= add_months(TO_DATE('08-JUL-2015'),-3) AND tax_mth >= add_months(TO_DATE('08-JUL-2015'), -14) AND eff_date =TO_DATE('08-JUL-2015') AND tax_type = '00'
用臨時表重寫復雜的子查詢。在臨時表中使用可以使用的索引來更快地檢索數據。
使用減號而不是存在的子查詢。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.