Używałbym ROWID:
UPDATE xyz SET x='Y' WHERE rowid IN (
SELECT r FROM (
SELECT ROWID r FROM xyz ORDER BY dbms_random.value
) RNDM WHERE rownum < n+1
)
Rzeczywisty powód, dla którego użyłbym ROWID, nie jest jednak dla wydajności (nadal wykona pełne skanowanie tabeli) - Twój SQL może nie aktualizować liczby wierszy, które chcesz, jeśli kolumna m
nie jest wyjątkowy.
Mając tylko 1000 wierszy, nie powinieneś się martwić o wydajność (może przy stu milionach wierszy). Bez żadnego indeksu w tej tabeli utknąłeś podczas pełnego skanowania tabeli w celu wybrania losowych rekordów.
[EDYTUJ:] „A co, jeśli jest 100 000 wierszy”
Cóż, to wciąż 3 rzędy wielkości mniej niż 100 milionów.
Uruchomiłem następujące:
create table xyz as select * from all_objects;
[utworzyłem około 50 000 wierszy w moim systemie - nieindeksowanych, tak jak Twoja tabela]
UPDATE xyz SET owner='Y' WHERE rowid IN (
SELECT r FROM (
SELECT ROWID r FROM xyz ORDER BY dbms_random.value
) RNDM WHERE rownum < 10000
);
commit;
Zajęło to około 1,5 sekundy. Może to była 1 sekunda, może do 3 sekund (oficjalnie nie zmierzyłem czasu, po prostu mrugnięcie zajęło wystarczająco dużo czasu).