Мне нужна помощь с некоторыми проблемами производительности:
У меня есть таблица CONTRATOS с 27 миллионами записей. Эта таблица имеет несколько столбцов, но важные из них: CONTRATO, CODIGO_ORIGEN.
Может существовать более одного CONTRATO для каждого CODIGO_ORIGEN, поэтому мне нужно сделать это:
SELECT DISTINCT
CODIGO_ORIGEN,
FIRST_VALUE(CONTRATO) OVER (PARTITION BY CODIGO_ORIGEN ORDER BY FECHA DESC) MAX_CONTRATO
FROM TABLE CONTRATOS;
После этого мы у меня 6 миллионов записей, хорошие ...
Мне нужно обновить записи NOT FOUND (CONTRATO) в таблице CONTRATOS, указав в столбце ESTADO значение 'E'.
Сначала я попытался сделать все за один шаг (запрос):
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), так что я могу улучшить производительность (верно?), но я все еще получаю слишком медленные результаты ...
План выполнения дает мне более 700 000 затрат на 27 миллионов записей ... Это слишком много или это нормально, учитывая количество записей? Он выполняет ТАБЛИЦУ ПОЛНОГО ПРОВЕРКИ обеих таблиц.
Это хорошая идея - использовать подсказки? Это хорошая идея, проходя через индексы? ... Каков наилучший вариант? используя Merge или Exists / Not существует / Not in ??
Кроме того, я не уверен в создании индекса для столбца ESTADO, потому что я обновляю это поле, и я прочитал, что создавать его не очень хорошая идея индекс в столбце, где вы выполняете обновления ... но мне нужно выполнить много запросов, связанных с ним.
Я использую представление V $ SESSION_LONGOPS и представление сеанса пользователя sysdba для мониторинга процесса ... Есть ли лучшая альтернатива?
Я не знаю, если я забуду что-то важное, я думаю, что я делаю.
Принесите мне немного света, пожалуйста. Любой совет приветствуется.
Заранее спасибо
С уважением.