我在Oracle中有一条更新语句,旨在更新“test_delete_me”表中的数万条记录。然而,该语句极其缓慢且低效。
此 Oracle 更新语句根据每个“ref_id”组内的行号序列重新计算“test_delete_me”表中的“ITEM”值,排除具有特定状态和空“ITEM”值的行。
这是我正在使用的更新语句:
UPDATE test_delete_me a
SET ITEM = (
SELECT row_num_seq - 1
FROM (
SELECT id, ref_id, ITEM, ROW_NUMBER() OVER (PARTITION BY ref_id ORDER BY id) AS row_num_seq
FROM test_delete_me
WHERE
ref_id IN (
SELECT ref_id
FROM test_delete_me
WHERE status = 3
GROUP BY ref_id
HAVING COUNT(CASE WHEN ITEM IS NULL THEN 1 END) > 2
)
)
WHERE id = a.id -- Match the main table's ID with the subquery's ID
AND row_num_seq NOT IN (1, 13) -- Exclude row_num_seq 1 and 13
)
WHERE EXISTS (
SELECT 1
FROM (
SELECT id, ref_id, ITEM, ROW_NUMBER() OVER (PARTITION BY ref_id ORDER BY id) AS row_num_seq
FROM test_delete_me
WHERE
ref_id IN (
SELECT ref_id
FROM test_delete_me
WHERE status = 3
GROUP BY ref_id
HAVING COUNT(CASE WHEN ITEM IS NULL THEN 1 END) > 2
)
)
WHERE id = a.id -- Match the main table's ID with the subquery's ID
AND row_num_seq NOT IN (1, 13) -- Exclude row_num_seq 1 and 13
);
我尝试了另一种方法,但仍然遇到相同的性能问题:
UPDATE test_delete_me a
SET ITEM = (
SELECT row_num_seq - 1
FROM (
SELECT b.id, b.ref_id, b.ITEM, ROW_NUMBER() OVER (PARTITION BY b.ref_id ORDER BY b.id) AS row_num_seq
FROM test_delete_me b
INNER JOIN (
SELECT ref_id
FROM test_delete_me
WHERE status = 3
GROUP BY ref_id
HAVING COUNT(CASE WHEN ITEM IS NULL THEN 1 END) > 2
) c ON b.ref_id = c.ref_id
) numbered
WHERE numbered.id = a.id
AND row_num_seq NOT IN (1, 13)
)
WHERE EXISTS (
SELECT 1
FROM (
SELECT b.id, b.ref_id, b.ITEM, ROW_NUMBER() OVER (PARTITION BY b.ref_id ORDER BY b.id) AS row_num_seq
FROM test_delete_me b
INNER JOIN (
SELECT ref_id
FROM test_delete_me
WHERE status = 3
GROUP BY ref_id
HAVING COUNT(CASE WHEN ITEM IS NULL THEN 1 END) > 2
) c ON b.ref_id = c.ref_id
) numbered
WHERE numbered.id = a.id
AND row_num_seq NOT IN (1, 13)
);
我需要帮助优化此更新语句以显着提高其性能。任何建议或见解将不胜感激!
尝试这样的事情:
MERGE INTO test_delete_me tgt
USING (SELECT *
FROM (SELECT ROWID row_id, id, ref_id, item,
COUNT(CASE WHEN ITEM IS NULL THEN 1 END) OVER (PARTITION BY ref_id) cnt,
ROW_NUMBER() OVER (PARTITION BY ref_id ORDER BY id) AS row_num_seq
FROM test_delete_me
WHERE status = 3)
WHERE cnt > 2
AND row_num_seq NOT IN (1, 13)) src
ON (src.row_id = tgt.rowid)
WHEN MATCHED THEN UPDATE SET tgt.item = src.row_num_seq - 1