【发布时间】:2020-05-30 13:51:09
【问题描述】:
我需要一些关于性能问题的帮助:
我有一个包含 2700 万条记录的表 CONTRATOS。此表有多个列,但重要的是:CONTRATO、CODIGO_ORIGEN。
每个 CODIGO_ORIGEN 可以存在多个 CONTRATO,所以我需要这样做:
SELECT DISTINCT
CODIGO_ORIGEN,
FIRST_VALUE(CONTRATO) OVER (PARTITION BY CODIGO_ORIGEN ORDER BY FECHA DESC) MAX_CONTRATO
FROM TABLE CONTRATOS;
在这之后,我们有 600 万条记录,好的记录...
我需要做的是用 ESTADO 列上的值“E”更新表 CONTRATOS 中的“未找到”记录 (CONTRATO)。
起初,我尝试一步完成所有事情(查询):
UPDATE / NOT EXISTS METHOD
--------------------------
UPDATE CONTRATOS C
SET ESTADO = 'E'
WHERE NOT EXISTS
(
SELECT 1
FROM
(
SELECT DISTINCT
CODIGO_ORIGEN,
FIRST_VALUE(CONTRATO) OVER (PARTITION BY CODIGO_ORIGEN ORDER BY FECHA DESC) MAX_CONTRATO
FROM TABLE CONTRATOS
) C2
WHERE C.CONTRATO = C2.MAX_CONTRATO
);
MERGE METHOD
---------------
MERGE INTO CONTRATOS C
USING
(
SELECT DISTINCT
CODIGO_ORIGEN,
FIRST_VALUE(CONTRATO) OVER (PARTITION BY CODIGO_ORIGEN ORDER BY FECHA DESC) MAX_CONTRATO
FROM TABLE CONTRATOS
) C2 ON (C.CONTRATO = C2.MAX_CONTRATO)
WHEN MATCHED THEN UPDATE SET ESTADO = 'E';
但是在看到它太慢(两种方法)之后,我尝试使用可以插入有效行的临时表来执行此操作:TEMP_CONTRATOS
Note: This point goes pretty fast (15 min)
INSERT INTO TEMP_CONTRATOS (MAX_CONTRATO, CODIGO_ORIGEN)
SELECT DISTINCT
CODIGO_ORIGEN,
FIRST_VALUE(CONTRATO) OVER (PARTITION BY CODIGO_ORIGEN ORDER BY FECHA DESC) MAX_CONTRATO
FROM TABLE CONTRATOS;
Note: Here is the problem again
UPDATE CONTRATOS C
SET ESTADO = 'E'
WHERE NOT EXISTS
(
SELECT 1
FROM TEMP_CONTRATOS TMP
WHERE C.CONTRATO = TMP.MAX_CONTRATO
);
我在两个表的列(CONTRATO/MAX_CONTRATO 和 CODIGO_ORIGEN)上都有一个索引,所以我可以提高性能(对吗?)但我的结果仍然太慢...
执行计划为 2700 万条记录提供了超过 700.000 的成本……考虑到记录的数量,是太多还是可以?它正在对两个表进行 TABLE FULL SCAN。
使用提示是个好主意吗?浏览索引是个好主意吗?...最好的选择是什么?使用合并或存在/不存在/不存在??
另外,我不确定是否要为 ESTADO 列创建索引,因为我正在更新该字段并且我读到在执行更新的列中创建索引不是一个好主意......但我有做很多查询加入它。
我正在使用 V$SESSION_LONGOPS 视图和 sysdba 用户的会话视图来监控进程...还有更好的选择吗?
我不知道我是否忘记了一些重要的事情,我想我会的。
请给我一些光。任何建议表示赞赏。
提前谢谢你
问候。
【问题讨论】:
-
您希望(大致)如何更新行?
-
我预计会更新 2000 万条记录:总共有 2700 万条记录,其中 650 万条是唯一的......所以.. 应该会影响 2000 万条记录。
-
能否添加上一次尝试的执行计划?临时表中有 6M 行,最好不要有索引访问计划(即 NL 连接)。
-
您可能正在将合并重写为 CTAS(创建表...作为选择);转换与修改。它会更快,您可以从压缩中受益;如果你有能力,你可以使用直接路径并使用并行。
-
我最近尝试的是更新与时态表匹配的那些,而不是更新那些不匹配的。这样我们正在更新 700 万条记录而不是 2000 万……然后将其余的更新为未找到……我不知道我是否解释得很好……是吗?谢谢!
标签: database oracle performance indexing plsql