N Update zufällige Zeilen in SQL
Habe ich die Tabelle mit über 1000 Zeilen.Ich habe zum aktualisieren einer Spalte("X") in der Tabelle " Y " für n ramdom Zeilen. Dafür habe ich folgende Abfrage
update xyz set X='Y' when m in (
'SELECT m FROM (SELECT m
FROM xyz
order by dbms_random.value
) RNDM
where rownum < n+1);
Gibt es eine weitere effiziente Art und Weise zu schreiben, diese Abfrage. Die Tabelle hat keinen index.
Bitte helfen?
- Wenn Sie nicht wirklich wichtig ist, welche Zeilen aktualisiert werden, was ist falsch mit, nur die Aktualisierung der top -
rownum
Zeilen? Wenn es keinen expliziten Auftrag an den Befehl, erhalten Sie eine nicht-guarunteed Bestellung (zugegeben, es ist wahrscheinlich, Datei-einfügen, aber nicht zwingend) in jedem Fall. Die Aktualisierung "eine zufällige Zeile" in der Regel bedeutet "I don' T care, die ein" - es sei denn, Sie benötigen es in der Tabelle verteilt werden, an welcher Stelle könnten Sie wählen nur jeder fünfte oder so etwas (möglicherweise durch dieid
Spalte). - Könnte sein, dass das update ist Teil eines Prozesses für die Probenahme-Datensätze für eine weitere überprüfung, Test, QA, etc. In dem Fall random versus nicht-ist bestimmt ein wichtiger Unterschied. Das ist, was ich nahm an, der OP sucht, wenn er fragte nach dem Zufallsprinzip.
- Oder für die Angabe von random contest belohnt; Sie könnte Recht haben.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Würde ich die ROWID:
Den eigentlichen Grund würde ich ROWID ist nicht für die Effizienz, obwohl (es wird noch ein full table scan) - Ihre SQL kann nicht aktualisieren Sie die Anzahl der Zeilen, die Sie wollen, wenn Spalte
m
ist nicht einzigartig.Mit nur 1000 Zeilen, die Sie nicht wirklich besorgt über die Effektivität (vielleicht mit hundert Millionen Zeilen). Ohne index auf diese Tabelle, in der Sie stecken dabei einen full table scan wählen, zufällige Datensätze.
[EDIT:] "Aber was ist, wenn es 100.000 Zeilen"
Gut, das ist immer noch 3 Größenordnungen weniger als 100 Millionen.
Lief ich die folgenden:
[erstellt etwa 50.000 Zeilen auf meinem system - nicht indiziert, genau wie deine Tabelle]
Dieser dauerte etwa 1,5 Sekunden. Vielleicht war es 1 Sekunde, vielleicht bis zu 3 Sekunden (nicht formal die Zeit, die es brauchte es nur genug Zeit zu blinken).
Können Sie die Leistung verbessern, durch Austausch der full table scan mit einer Probe.
Das erste problem, das Sie in ausgeführt wird, dass Sie nicht verwenden können, die PROBE in einem DML-Unterabfrage
ORA-30560: SAMPLE clause not allowed
. Aber logisch das ist, was benötigt wird:Können Sie dies umgehen, indem mit Hilfe einer collection zu speichern, die rowids, und aktualisieren Sie dann die Zeilen mit der rowid-Sammlung. Normalerweise bricht eine Abfrage in einzelne Teile und kleben Sie zusammen mit PL/SQL führt zu schrecklichen Leistung. Aber in diesem Fall können Sie immer noch sparen eine Menge Zeit durch eine signifikante Reduzierung der Menge der zu lesenden Daten.
Habe ich mal einen einfachen test mit 100.000 Zeilen (für eine Tabelle mit nur zwei Spalten) und N = 100.
Die ursprüngliche version dauerte 0.85 Sekunden, @Gerrat die Antwort dauerte 0,7 Sekunden, und der PL/SQL-version nahm 0.015 Sekunden.
Aber das ist nur ein Szenario, ich habe nicht genügend Informationen zu sagen, meine Antwort wird immer besser. Als N erhöht sich die sampling-Vorteil verloren, und die Schrift wird wichtiger sein als das Lesen. Wenn Sie eine sehr kleine Menge von Daten, die PL/SQL-Kontext-switching-overhead in meiner Antwort machen Sie es langsamer als @Gerrat Lösung.
Für performance-Probleme, die Größe der Tabelle in Byte ist in der Regel viel wichtiger als die Größe in Zeilen. 1000 Zeilen, die mit einem terabyte Speicherplatz ist viel größer als 100 Mio Zeilen, die nur mit einem gigabyte.
Hier sind einige Probleme zu berücksichtigen, mit meiner Antwort:
N
ändern, müssen Sie dynamisches SQL verwenden, um ändern Sie die Prozent.Folgende Lösung funktioniert Prima. Es ist robust und scheint ähnlich zu sein
sample()
:Bedenken Sie, dass alias
rnd
enthalten sein müssen in der select-Klausel. Sonst ändert sich die omptimizer der filter predicat ausRND<0.1
zuDBMS_RANDOM.VALUE()<0.1
. In diesem Falldbms_random.value
wird nur einmal ausgeführt.Wie bereits in der Antwort @JonHeller, die beste Lösung bleibt die pl/sql-code-block, da es ermöglicht, um full table scan. Hier ist mein Vorschlag: