Oracle 中缓慢且低效的更新语句

问题描述 投票:0回答:1

我在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)
);

我需要帮助优化此更新语句以显着提高其性能。任何建议或见解将不胜感激!

sql oracle performance optimization
1个回答
0
投票

尝试这样的事情:

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
© www.soinside.com 2019 - 2024. All rights reserved.