各位,最近参与了一项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 子句中重复子查询。
我认为你的更新可以重写为:
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”作为月份,附加的第三个参数使日期字符串转换 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
,因为这会返回列表。因此,您的支票将变为并且 COALESCE(ecm, esm, ...) 不为 null
。 - 实际上并不需要 COALESCE,因为 HAVING 子句有效地排除了所有值为 NULL 和 0 的行。
- 用于使子查询相关的谓词成为目标表和源子查询之间的连接条件,这意味着您不再需要之前在相关子查询中使用的外部查询。
- 我将条件移至更新部分的 WHERE 子句中,以仅更新具有特定纳税月份的行。我很确定它可以留在 join 子句中,但我认为如果将其放入更新的 WHERE 子句中,意图会更清晰。
我会测试新的 MERGE 语句以确保它执行正确的操作(或修复它直到正确),然后看看这对性能有何影响。
如果它仍然在 AWR 中作为问题陈述弹出,那么我会进一步研究如何调整它;也许需要更新/附加索引,也许需要物化 View 等。
关于sql - 如何对下面的更新sql进行SQL调优,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51206430/