Несколько из нас советовали вам in your previous question, что вы должны попытаться решить проблему производительности путем настройки оператора SQL, а не стремясь подорвать целостность транзакции. Теперь вы разместили обновление, которое мы можем вам помочь.
Дело в UPDATE заключается в том, что это всего лишь вариант SELECT: база данных должна найти строки, прежде чем она сможет их изменить. Поэтому мы часто можем сократить время выполнения, настроив путь доступа. Например, мы можем запустить EXPLAIN PLAN для операторов обновления:
explain plan for
UPDATE baseinformation w
SET good_item_id = (SELECT id FROM item e WHERE e.id = w.id)
/
без доступа к вашему Explain Plan, статистике и данные перекосы, трудно предложить жесткий совет. На лицевой стороне вашего заявления будет выполнено одно из следующих сообщений: item
для каждая строка в baseinformation
. Даже если доступ является INDEX UNIQUE SCAN, 60 миллионов из них много читаются. Если есть строки в baseinformation
, которые не имеют соответствия id
в item
, он становится еще дороже. Как отметил @DavidAldridge, база данных все же может реализовать более эффективный путь, но если ваше заявление работает в течение трех дней, похоже, оно не приняло правильного решения.
Так что вам нужно сделать, чтобы оптимизатор принял правильное решение. Одно очевидное - убедиться, что статистика базы данных является точной, как для таблиц, так и для любых индексов, которые у них есть.
Другое дело - преобразовать эти индивидуальные запросы в заданную операцию, что должно обеспечить более эффективный путь доступа.Ваш SQL как представленные обновления baseinformation.good_item_id
до item.id
если item.id
соответствует baseinformation.id
. Таким образом, это утверждение логически эквивалентно ...
update baseinformation w
set w.good_item_id = w.id
where w.id in (select e.id from item e)
/
... как это один ...
update baseinformation w
set w.good_item_id = w.id
where exists (select e.id from item e where e.id = w.id)
/
Если baseinformation
имеет огромное количество строк и item
имеет крошечное количество совпадающих строк то более предпочтительным является формулировка WHERE ... IN. Если baseinformation
является крошечным и item
огромен, тогда ГДЕ СУЩЕСТВУЕТ ... формулировка, вероятно, будет работать лучше. Если обе таблицы примерно эквивалентны в количестве строк, чем любой подход может быть лучше, в зависимости от индексов, кластеризации и т. Д., Поэтому вам нужно будет сравнить оба.
Другим подходом было бы выполнить объединение двух таблиц. Вы можете сделать это с MERGE заявлением ...
merge into baseinformation w
using (select id from item) e
on (e.id = w.id)
when matched then
update
set w.good_item_id = e.id
/
... или с обновляемым видом на линии ...
update (
select
e.id as item_id
, w.good_item_id
from baseinformation w
join item e
on (e.id = w.id)
)
set good_item_id = item_id
/
Вероятно, они будут иметь аналогичные профили производительности в суб- запросов, но опять же стратегии индексирования или перекос данных могут помочь одному из остальных.
На самом деле ответ на свой вопрос :)
"есть решение или команды в чистом Oracle SQL"
No. заявление SQL является атомным. Невозможно зафиксировать прирост инструкции UPDATE. Вы можете ограничить UPDATE искусственным подмножеством строк, например.
update baseinformation w
set w.good_item_id = w.id
where w.id in (select e.id from item e)
and w.good_item_id is null
and rownum <= 20000
/
Мы могли бы использовать такой оператор в блоке PL/SQL для обновления и фиксации кусков в двадцать тысяч строк. Однако это приведет к более длительному истекшему времени, потому что вы будете постоянно запускать ПОЛНЫЙ ТАБЛИЦЫ СКАНИРОВАНИЯ baseinformation
. Кроме того, этот подход вызывает проблемы с последовательностью транзакций: любой запрос сеанса baseinformation
на основе good_item_id
получит потенциально обманчивый набор результатов.
Единственное преимущество инкрементных коммитов заключается в том, что оно дает нам точку восстановления, если по какой-либо причине процесс обновления не работает. Это не является незначительным преимуществом при длительном процессе, но главным приоритетом должно быть решение «долговременного» аспекта.
Что касается совершения с другой сессии, это невозможно. Oracle накладывает уровень изоляции Read Committed. Это означает, что сеансы могут видеть только измененные записи после того, как изменения сессии совершили изменения. В Oracle нет грязных чтений. Это означает, что один сеанс не может фиксировать изменения в другом сеансе. Find out more.
Как долго? У вас есть индекс в обеих таблицах 'id'? –
Вам определенно нужны индексы для item.id и baseinformation.good_item_id для вышеупомянутого, чтобы иметь достойную производительность. – John
PLSQL здесь не правильный выбор. Когда вы сможете сделать это в одном SQL, вы должны сделать это в одном SQL. Правильное решение - понять, почему SQL работает медленно и настраивает его. Являются ли статистика на обеих таблицах актуальной? Есть ли спорные вопросы?Любые индексы, триггеры в таблице 'baseinformation', которые могут замедлить обновление и т. Д., – toddlermenot