3 Stimmen

Wie optimiert man eine MySQL-Abfrage so, dass ein ausgewählter Wert in einer WHERE-Klausel nur einmal berechnet wird?

Ich muss auf effiziente Weise 10 Zeilen aus meiner Tabelle zufällig auswählen.

Ich habe festgestellt, dass folgendes gut funktioniert (nach der Abfrage wähle ich einfach in PHP 10 zufällige Elemente aus den 10 bis 30 aus, die ich aus der Abfrage erhalte):

SELECT * FROM Produkt WHERE RAND() <= (SELECT 20 / COUNT(*) FROM Produkt)

Die Unterabfrage wird jedoch, obwohl relativ günstig, für jede Zeile in der Tabelle berechnet. Wie kann ich das verhindern? Mit einer Variable? Einem Join?

Danke!

2voto

Paul Sasik Punkte 76202

Eine Variable würde das tun. Etwas wie das:

SELECT @myvar := (SELECT 20 / COUNT(*) FROM product);
SELECT * FROM product WHERE RAND() <= @myvar;

Oder, aus dem MySQL-Mathematikfunktionen Dokument:

Sie können eine Spalte mit RAND()-Werten in einer ORDER BY-Klausel nicht verwenden, da ORDER BY die Spalte mehrmals auswerten würde. Sie können jedoch Zeilen in zufälliger Reihenfolge abrufen, indem Sie dies tun:

mysql> SELECT * FROM tbl_name ORDER BY
> RAND();

ORDER BY RAND() in Kombination mit LIMIT ist nützlich, um eine zufällige Stichprobe aus einer Menge von Zeilen auszuwählen:

mysql> SELECT * FROM table1, table2
> WHERE a=b AND c ORDER BY RAND()
> LIMIT 1000;

RAND() ist nicht dazu gedacht, ein perfekter Zufallszahlengenerator zu sein. Es ist ein schneller Weg, um zufällige Zahlen auf Abruf zu generieren, der zwischen Plattformen für dieselbe MySQL-Version portabel ist.

1voto

Roman Punkte 5611
 SELECT * FROM produkt ORDER BY RAND() LIMIT 10

1voto

bot403 Punkte 2083

Es ist ein sehr spezifischer Trick für mysql, aber indem er in einer weiteren Unterabfrage eingewickelt wird, wird MySQL ihn zu einer Konstantentabelle machen und nur einmal berechnen.

 SELECT \* FROM produkt WHERE RAND() <= (
  select \* from ( SELECT 20 / COUNT(\*) FROM produkt ) as const\_table
 )

0voto

FoneyOp Punkte 346

Verwenden Sie nicht order by rand(). Dies führt zu einem Table-Scan. Wenn Sie viele Daten in Ihrer Tabelle haben, ist dies überhaupt nicht effizient. Bestimmen Sie zuerst, wie viele Zeilen sich in der Tabelle befinden:

select count(*) from table könnte für Sie funktionieren, obwohl Sie diesen Wert wahrscheinlich eine Weile zwischenspeichern sollten, da dies bei großen Datensätzen langsam sein kann.

explain select * from table gibt Ihnen die Datenbankstatistiken für die Tabelle (wie viele Zeilen die Statistik in der Tabelle denkt, dass sie enthält). Dies ist viel schneller, allerdings weniger genau und noch ungenauer für InnoDB-Tabellen.

Sobald Sie die Anzahl der Zeilen haben, sollten Sie etwas Code schreiben wie:

Pseudocode:

String SQL = "SELECT * FROM product WHERE id IN (";
for (int i=0;i

`

Dies gibt Ihnen eine schnelle Suche nach dem Primärschlüssel und vermeidet den Table-Scan.

`

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X