Вы можете улучшить производительность, заменив полное сканирование таблицы образцом.
Первая проблема, с которой вы столкнулись, заключается в том, что вы не можете использовать SAMPLE в подзапросе DML, ORA-30560: SAMPLE clause not allowed
. Но по логике это то, что нужно:
UPDATE xyz SET x='Y' WHERE rowid IN (
SELECT r FROM (
SELECT ROWID r FROM xyz sample(0.15) ORDER BY dbms_random.value
) RNDM WHERE rownum < 100/*n*/+1
);
Вы можете обойти это, используя коллекцию для хранения строк, а затем обновить строки, используя коллекцию строк. Обычно разбиение запроса на отдельные части и склейка их вместе с PL / SQL приводит к ужасной производительности. Но в этом случае вы все равно можете сэкономить много времени, значительно сократив количество прочитанных данных.
declare
type rowid_nt is table of rowid;
rowids rowid_nt;
begin
--Get the rowids
SELECT r bulk collect into rowids
FROM (
SELECT ROWID r
FROM xyz sample(0.15)
ORDER BY dbms_random.value
) RNDM WHERE rownum < 100/*n*/+1;
--update the table
forall i in 1 .. rowids.count
update xyz set x = 'Y'
where rowid = rowids(i);
end;
/
Я выполнил простой тест с 100 000 строк (для таблицы, содержащей только два столбца), и N = 100.
Первоначальная версия заняла 0,85 секунды, ответ @ Gerrat занял 0,7 секунды, а версия PL / SQL - 0,015 секунды.
Но это только один сценарий, у меня недостаточно информации, чтобы сказать, что мой ответ всегда будет лучше. По мере увеличения N преимущество выборки теряется, и запись будет более значимой, чем чтение. Если у вас очень маленький объем данных, издержки переключения контекста PL / SQL в моем ответе могут сделать его медленнее, чем решение @ Gerrat.
Для проблем с производительностью размер таблицы в байтах обычно гораздо важнее, чем размер в строках. 1000 строк, которые используют терабайт пространства, намного больше, чем 100 миллионов строк, которые используют только гигабайт.
Вот некоторые проблемы, которые следует рассмотреть с моим ответом:
- Выборка не всегда возвращает именно тот процент, который вы просили. При 100 000 строк и размере выборки 0,15% количество возвращаемых строк составило 147, а не 150. Именно поэтому я использовал 0,15 вместо 0,10. Вам нужно немного перепроверять, чтобы убедиться, что вы получите больше, чем N. Сколько нужно перепроверять? Я понятия не имею, вам, вероятно, придется проверить его и выбрать безопасный номер.
- Вам нужно знать приблизительное количество строк, чтобы выбрать процент.
- Процент должен быть литералом, поэтому при изменении количества строк и
N
вам потребуется использовать динамический SQL для изменения процента.