В настоящее время я запускаю следующие отдельные обновления в PL / SQL Oracle 12.1, и мне нужно знать, как повысить производительность с помощью массового обновления, поскольку для их завершения требуется несколько часов или любой другой стратегии в этом отношении.
Проблема заключается в том, что мне нужно обновить несколько столбцов с идентичным набором условий (этих CASE WHEN
операторов) из таблицы (LARGE_TBL
), в которой есть несколько сотен тысяч записей (в самой MAIN_TBL
есть несколькосотни тысяч записей. Обе таблицы имеют индексы LT_ID
и MT_ID
).
Существует несколько других UPDATES
с разными значениями для LT.IDX_2
и MT.IDX_2
(для краткости я их исключил) и отображается только IDX_2 = G
(есть другие идентичные UPDATE
с другими IDX_2
значениями).
UPDATE MAIN_TBL MT
SET
MT.STOP_FLAG = (
SELECT
CASE
WHEN
NOT EXISTS (SELECT 1 FROM LARGE_TBL LT WHERE LT.LT_ID = MT.MT_ID AND LT.IDX_2 = 'G')
OR (SELECT LT.COL_1 FROM LARGE_TBL LT WHERE LT.LT_ID = MT.MT_ID AND LT.IDX_2 = 'G') IS NULL
OR (SELECT LT.COL_1 FROM LARGE_TBL LT WHERE LT.LT_ID = MT.MT_ID AND LT.IDX_2 = 'G') <> 'Y'
THEN 'SF01'
ELSE MT.STOP_FLAG
END
FROM DUAL
),
MT.ES = (
SELECT
CASE
WHEN
NOT EXISTS (SELECT 1 FROM LARGE_TBL LT WHERE LT.LT_ID = MT.MT_ID AND LT.IDX_2 = 'G')
OR (SELECT LT.COL_1 FROM LARGE_TBL LT WHERE LT.LT_ID = MT.MT_ID AND LT.IDX_2 = 'G') IS NULL
OR (SELECT LT.COL_1 FROM LARGE_TBL LT WHERE LT.LT_ID = MT.MT_ID AND LT.IDX_2 = 'G') <> 'Y'
THEN 'E'
ELSE MT.ES
END
FROM DUAL
),
MT.PW = (
SELECT
CASE
WHEN
NOT EXISTS (SELECT 1 FROM LARGE_TBL LT WHERE LT.LT_ID = MT.MT_ID AND LT.IDX_2 = 'G')
OR (SELECT LT.COL_1 FROM LARGE_TBL LT WHERE LT.LT_ID = MT.MT_ID AND LT.IDX_2 = 'G') IS NULL
OR (SELECT LT.COL_1 FROM LARGE_TBL LT WHERE LT.LT_ID = MT.MT_ID AND LT.IDX_2 = 'G') <> 'Y'
THEN 'W'
ELSE MT.PW
END
FROM DUAL
),
MT.UPDATE_DT = SYSDATE
WHERE
MT.STOP_FLAG IS NULL
AND MT.IDX_2 = 'G'
AND MT.ES IS NULL
AND MT.SS = 'C'
AND MT.PW = 'A';
UPDATE MAIN_TBL MT
SET
MT.STOP_FLAG = (
SELECT
CASE
WHEN
NOT EXISTS (SELECT 1 FROM LARGE_TBL LT WHERE LT.LT_ID = MT.MT_ID AND LT.IDX_2 = 'G')
OR (SELECT LT.COL_2 FROM LARGE_TBL LT WHERE LT.LT_ID = MT.MT_ID AND LT.IDX_2 = 'G') IS NULL
OR (SELECT LT.COL_2 FROM LARGE_TBL LT WHERE LT.LT_ID = MT.MT_ID AND LT.IDX_2 = 'G') <> 'Y'
THEN 'SF02'
ELSE MT.STOP_FLAG
END
FROM DUAL
),
MT.ES = (
SELECT
CASE
WHEN
NOT EXISTS (SELECT 1 FROM LARGE_TBL LT WHERE LT.LT_ID = MT.MT_ID AND LT.IDX_2 = 'G')
OR (SELECT LT.COL_2 FROM LARGE_TBL LT WHERE LT.LT_ID = MT.MT_ID AND LT.IDX_2 = 'G') IS NULL
OR (SELECT LT.COL_2 FROM LARGE_TBL LT WHERE LT.LT_ID = MT.MT_ID AND LT.IDX_2 = 'G') <> 'Y'
THEN 'E'
ELSE MT.ES
END
FROM DUAL
),
MT.PW = (
SELECT
CASE
WHEN
NOT EXISTS (SELECT 1 FROM LARGE_TBL LT WHERE LT.LT_ID = MT.MT_ID AND LT.IDX_2 = 'G')
OR (SELECT LT.COL_2 FROM LARGE_TBL LT WHERE LT.LT_ID = MT.MT_ID AND LT.IDX_2 = 'G') IS NULL
OR (SELECT LT.COL_2 FROM LARGE_TBL LT WHERE LT.LT_ID = MT.MT_ID AND LT.IDX_2 = 'G') <> 'Y'
THEN 'W'
ELSE MT.PW
END
FROM DUAL
),
MT.UPDATE_DT = SYSDATE
WHERE
MT.STOP_FLAG IS NULL
AND MT.IDX_2 = 'G'
AND MT.ES IS NULL
AND MT.SS = 'C'
AND MT.PW = 'A';
Проблема в том, что, например, в случае выше, второй UPDATE
зависит от первого UPDATE
, потому что второе UPDATE
должно выполняться только если MT.STOP_FLAG IS NULL
.Поэтому, если MT.STOP_FLAG
установлено с первым UPDATE
(с MT.STOP_FLAG = SF01
), второе UPDATE
не должно выполняться, так как предложение WHERE
не будет выполнено (MT.STOP_FLAG IS NULL
).Другими словами, порядок выполнения этих UPDATE
имеет значение.
Я не использовал функцию массового обновления PL / SQL, поэтому я не уверен, как к этому подойти.Должен ли я создать курсор для извлечения всех необходимых столбцов из таблицы LARGE_TBL
с соответствующими условиями, например, IDX_2 = G
или IDX_2 = R
, которая является относительно большой таблицей (несколько сотен тысяч записей), а затем извлечь их с помощью BULK COLLECT
в несколько определенных TYPE
и, наконец, использовать один FORALL
с несколькими отдельными операторами UPDATE
?Или несколько FORALL
, по одному для каждого UPDATE
?
Если использовать курсоры, как мне обработать первый элемент в моем операторе CASE WHEN
, где мне нужно убедиться, что запись существует?или нет?