schnelle Auswahl einer zufälligen Zeile aus einer großen Tabelle in mysql

42

Was ist eine schnelle Möglichkeit, eine zufällige Zeile aus einer großen MySQL-Tabelle auszuwählen?

Ich arbeite in PHP, aber ich bin an jeder Lösung interessiert, auch wenn es in einer anderen Sprache ist.

    
lajos 17.10.2008, 07:38
quelle

24 Antworten

45

Nimm alle IDs, wähle einen zufälligen aus und lade die ganze Zeile ein.

Wenn Sie wissen, dass die IDs ohne Löcher sequentiell sind, können Sie einfach die Max-Zahl nehmen und eine zufällige ID berechnen.

Wenn es hier und da Löcher gibt, aber meistens sequenzielle Werte, und Sie sich nicht um eine leicht verzerrte Zufälligkeit kümmern, greifen Sie den Maximalwert, berechnen Sie eine ID und wählen Sie die erste Zeile mit einer ID gleich oder höher als die du hast berechnet. Der Grund für die Verzerrung ist, dass IDs, die solchen Löchern folgen, eine höhere Wahrscheinlichkeit haben, ausgewählt zu werden als solche, die einer anderen ID folgen.

Wenn Sie nach dem Zufallsprinzip sortieren, haben Sie einen schrecklichen Table-Scan auf Ihren Händen und das Wort schnell trifft nicht auf eine solche Lösung zu.

Tun Sie das nicht, noch sollten Sie eine GUID bestellen, es hat das gleiche Problem.

    
Lasse Vågsæther Karlsen 17.10.2008, 07:42
quelle
36

Ich wusste, dass es eine Möglichkeit geben muss, dies in einer einzigen Abfrage auf schnelle Weise zu tun. Und hier ist es:

Ein schneller Weg ohne Einbeziehung von externem Code, ein großes Lob an

Ссылка

%Vor%     
Vinko Vrsalovic 17.10.2008 08:19
quelle
30

MediaWiki verwendet einen interessanten Trick (für Wikipedia Special: Random-Funktion): die Tabelle mit den Artikeln hat eine zusätzliche Spalte mit einer Zufallszahl (generiert, wenn der Artikel erstellt wird). Um einen zufälligen Artikel zu erhalten, generieren Sie eine Zufallszahl und rufen Sie den Artikel mit dem nächstgrößeren oder kleineren Wert in der Zufallszahlenspalte ab. Mit einem Index kann dies sehr schnell sein. (Und MediaWiki ist in PHP geschrieben und für MySQL entwickelt.)

Dieser Ansatz kann ein Problem verursachen, wenn die resultierenden Zahlen schlecht verteilt sind; IIRC, das wurde in MediaWiki behoben, wenn du dich also dafür entscheidest, solltest du einen Blick auf den Code werfen, um zu sehen, wie er gerade ausgeführt wird (wahrscheinlich wird die Zufallszahlenspalte periodisch neu generiert).

    
CesarB 18.10.2008 04:39
quelle
11

Hier ist eine Lösung, die ziemlich schnell läuft und eine bessere zufällige Verteilung erhält, ohne von ID-Werten abhängig zu sein, die zusammenhängend sind oder bei 1 beginnen.

%Vor%     
Bill Karwin 17.10.2008 18:16
quelle
3

Fügen Sie jeder Zeile eine Spalte hinzu, die einen berechneten zufälligen Wert enthält, und verwenden Sie diese in der Sortierklausel, wobei Sie bei der Auswahl auf ein Ergebnis beschränken. Dies funktioniert schneller als die Tabellensuche, die ORDER BY RANDOM() verursacht.

Aktualisierung: Sie müssen immer noch einige zufällige Werte berechnen, bevor Sie die Anweisung SELECT beim Abrufen ausgeben, z. B.

%Vor%     
Rob 26.09.2008 22:17
quelle
3

Vielleicht könnten Sie etwas tun wie:

%Vor%

Dies setzt voraus, dass Ihre ID-Nummern sequenziell und ohne Lücken sind.

    
davr 26.09.2008 22:15
quelle
1

Ein einfacher, aber langsamer Weg wäre (gut für kleinere Tische)

%Vor%     
Vinko Vrsalovic 17.10.2008 07:39
quelle
1

Im Pseudocode:

%Vor%

Dies setzt voraus, dass id ein eindeutiger (primärer) Schlüssel ist.

    
Anders Sandvig 17.10.2008 07:53
quelle
1

Es gibt eine andere Möglichkeit, um zufällige Zeilen mit nur einer Abfrage und ohne Reihenfolge von rand () zu erzeugen. Es beinhaltet benutzerdefinierte Variablen. Siehe zum Erstellen zufälliger Zeilen aus einer Tabelle

    
Ilan Hazan 30.11.2009 21:01
quelle
1

Um zufällige Zeilen aus einer Tabelle zu finden, verwenden Sie ORDER BY RAND () nicht, weil es MySQL zwingt, eine vollständige Dateisortierung durchzuführen und erst dann die erforderliche Anzahl von Zeilen zu ermitteln. Um diese vollständige Dateisortierung zu vermeiden, verwenden Sie die Funktion RAND () nur in der WHERE-Klausel. Es stoppt, sobald es die erforderliche Anzahl von Zeilen erreicht. Sehen Ссылка

    
Sagi Bron 25.01.2011 13:50
quelle
1

Wenn Sie die Zeile in dieser Tabelle nicht löschen, ist der effizienteste Weg:

(Wenn Sie die Mininum-ID kennen, überspringen Sie sie einfach)

%Vor%     
parm.95 31.05.2010 20:53
quelle
1

Für die Auswahl mehrerer zufälliger Zeilen aus einer gegebenen Tabelle (zB "Wörter") hat unser Team diese Schönheit entwickelt:

%Vor%     
Belogradchik Rocks 23.04.2009 09:10
quelle
0

Die klassische "SELECT ID FROM Tabelle ORDER BY RAND () LIMIT 1" ist eigentlich in Ordnung.

Siehe folgenden Auszug aus dem MySQL-Handbuch:

Wenn Sie LIMIT row_count mit ORDER BY verwenden, beendet MySQL die Sortierung, sobald es die ersten row_count Zeilen des sortierten Ergebnisses gefunden hat, anstatt das gesamte Ergebnis zu sortieren.

    
igelkott 27.09.2008 13:12
quelle
0

Mit einer Bestellung machen Sie eine vollständige Scan-Tabelle. Es ist am besten, wenn Sie eine Auswahl zählen (*) und später eine zufällige Zeile = rownum zwischen 0 und der letzten Registrierung

erhalten     
MazarD 17.10.2008 07:44
quelle
0

Sehen Sie sich diesen Link von Jan Kneschke oder diese SO-Antwort , da beide die gleiche Frage diskutieren . Die SO-Antwort geht auch über verschiedene Optionen und hat einige gute Vorschläge, die auf Ihre Bedürfnisse abgestimmt sind. Jan geht auf die verschiedenen Möglichkeiten und Leistungsmerkmale ein. Er endet mit der folgenden optimierten Methode, um dies in einem MySQL-Select zu tun:

%Vor%

HTH,

-Dipin

    
Dipin 20.03.2009 22:07
quelle
0

Ich bin ein wenig neu in SQL, aber wie wäre es mit einer Zufallszahl in PHP und mit

%Vor%

Das löst das Problem mit Löchern in der Tabelle nicht.

Aber hier ist eine Wendung auf Lassevks Vorschlag:

%Vor%

Verwenden Sie mysql_num_rows () in PHP, um eine Zufallszahl basierend auf dem obigen Ergebnis zu erstellen:

%Vor%

Nebenbei bemerkt, wie langsam ist SELECT * FROM the_table :
Erstellen Sie eine Zufallszahl basierend auf mysql_num_rows() und verschieben Sie dann den Datenzeiger auf diesen Punkt mysql_data_seek() . Wie langsam wird das auf großen Tischen mit sage und schreibe eine Million Zeilen sein?

    
Adde 19.12.2008 22:27
quelle
0

Ich stieß auf das Problem, bei dem meine IDs nicht sequenziell waren. Was ich daraus gemacht habe.

%Vor%

Die zurückgegebenen Zeilen sind ungefähr 5, aber ich beschränke sie auf 1.

Wenn Sie eine weitere WHERE-Klausel hinzufügen möchten, wird es etwas interessanter. Angenommen, Sie möchten nach Produkten mit Rabatt suchen.

%Vor%

Was Sie tun müssen, ist sicherzustellen, dass Sie genug Ergebnis zurückgeben, weshalb ich es auf 100 gesetzt habe. Eine WHERE Rabatt & lt; .2 Klausel in der Unterabfrage war 10x langsamer, daher ist es besser, mehr Ergebnisse und Limits zurückzugeben .

    
bikedorkseattle 30.05.2012 22:37
quelle
0

Ich sehe hier eine Menge Lösung. Ein oder zwei scheint in Ordnung, aber andere Lösungen haben einige Einschränkungen. Aber die folgende Lösung wird für alle Situationen funktionieren:

%Vor%

Hier, ID, muss nicht sequenziell sein. Es könnte jede Primärschlüssel- / Unique- / Autoinkrement-Spalte sein. Bitte beachten Sie die folgende Schnellste Möglichkeit zur Auswahl von a zufällige Reihe von einer großen MySQL-Tabelle

Danke Zillur - www.techinfobest.com

    
Zillur 22.02.2014 09:22
quelle
0

Verwenden Sie die folgende Abfrage, um die zufällige Zeile

zu erhalten %Vor%     
MANOJ 24.02.2015 06:17
quelle
0

In meinem Fall hat meine Tabelle eine ID als Primärschlüssel, auto-increment ohne Lücken, also kann ich COUNT(*) oder MAX(id) verwenden, um die Anzahl der Zeilen zu erhalten.

Ich habe dieses Skript gemacht, um die schnellste Operation zu testen:

%Vor%

Die Ergebnisse sind:

  • Anzahl: 36.8418693542479 ms
  • Max: 0.241041183472 ms
  • Bestellung : 0.216960906982 ms

Antwort mit der Bestellmethode:

%Vor%     
Toni Almeida 15.05.2015 14:27
quelle
0

Ich habe das benutzt und der Job war erledigt die Referenz von hier

> %Vor%     
Yousef Altaf 12.03.2016 16:36
quelle
0

Erstellen Sie eine Funktion, um dies wahrscheinlich die beste Antwort und schnellste Antwort hier zu tun!

Pros - Funktioniert auch mit Lücken und extrem schnell.

%Vor%

Bitte denken Sie daran, dass dieser Code nicht getestet wurde, aber ein funktionierendes Konzept ist, um zufällige Einträge auch mit Lücken zurückzugeben. Solange die Lücken nicht groß genug sind, um ein Ladezeitproblem zu verursachen.

    
RandomGuest 29.03.2017 18:58
quelle
-1

Schnelle und schmutzige Methode:

%Vor%

Die Komplexität der ersten Abfrage ist O (1) für MyISAM-Tabellen.

Die zweite Abfrage wird von einem Tabellenscan begleitet. Komplexität = O (n)

Schmutzige und schnelle Methode:

Behalten Sie eine separate Tabelle nur für diesen Zweck. Sie sollten immer dieselben Zeilen in diese Tabelle einfügen, wenn Sie sie in die Originaltabelle einfügen. Annahme: Keine DELETEs.

%Vor%

Wenn DELETEs erlaubt sind,

%Vor%

Die Gesamtkomplexität ist O (1).

    
yogman 18.10.2008 05:18
quelle
-2

SELECT DISTINCT * FROM yourTable WHERE 4 = 4 LIMIT 1;

    
proggL 22.01.2014 02:53
quelle

Tags und Links