Mit
select floor(rand() * m.maxId + 1) as randomId
from Articles a
join (SELECT MAX(id) maxId FROM Articles) m
limit 100
erhalten Sie 100 zufällige IDs erstellen. Ich nehme 100, weil Sie Lücken in Ihrer ID-Spalte haben, also wird die Wahrscheinlichkeit, dass Sie nicht genug vorhandene IDs erhalten, (sehr) klein sein. Dann können Sie dieses Ergebnis verwenden, um nur 6 Zeilen mit dieser IDs zu wählen:
select distinct a.*
from (
select id, floor(rand() * m.maxId + 1) as randomId
from Articles a
join (SELECT MAX(id) maxId FROM Articles) m
limit 100
) r
join Articles a on a.id = r.randomId
order by r.id -- only need it for small tables. will slow down the query on big tables
limit 6
Der beste Wert für LIMIT
im subselect hängt von Prozentsatz von Lücken in Ihrem ids. 100 sollte ausreichen und schnell sein.
aktualisieren
Wenn Sie mit dem category
filtern müssen Sie eine WHERE a.category = 'entertainment'
Klausel vor ORDER BY
und LIMIT
hinzufügen können. In diesem Fall müssen Sie jedoch die Anzahl der generierten zufälligen IDs anpassen.
Zum Beispiel: Wenn Sie 1M Artikel eingefügt haben, aber 10% davon gelöscht wurden, dann gibt es im Durchschnitt 90 zufällig generierte IDs. Wenn jetzt 10% der Artikel category = 'entertainment'
haben, entspricht ein Durchschnitt von 9 zufälligen Zeilen der Bedingung. Durchschnitt bedeutet - es könnte 3 sein und könnte auch 16 sein. Also müssen Sie mehr zufällige IDs generieren, um sicher zu sein, dass Sie mindestens 6 Artikel erhalten. Mit LIMIT 1000
im Subselect erhalten Sie durchschnittlich 90 zufällige Unterhaltungsartikel. Auf diese Weise ist es sehr unwahrscheinlich, dass Sie weniger als 6 bekommen. Sie müssen also die Statistiken Ihrer Tabelle kennen, um eine gute LIMIT
auszuwählen.
Ein weiteres Problem mit der Klausel WHERE
ist, dass MySQL die Join-Reihenfolge möglicherweise umkehren kann, um einen Index zum Filtern zu verwenden. Dies kann für eine kleine Anzahl generierter Zufalls-IDs schneller sein, ist jedoch möglicherweise langsamer, wenn die LIMIT
im Subselect sehr groß ist. Sie können die Verknüpfungsreihenfolge erzwingen, indem Sie STRIGHT_JOIN
anstelle von JOIN
verwenden - aber in meinem Test mit LIMIT 10000
hat es keinen messbaren Unterschied gemacht.
Wenn Ihr Zustand zu selektiv ist (z. B. nur 1% der Artikel haben category='entertainment'
), kann ein einfacher ORDER BY RAND()
schneller sein, weil Sie sonst zu viele zufällige IDs erstellen müssten. Aber bis zu 10K Zeilen, die zu Ihrem Zustand ORDER BY RAND()
passen, sind schnell genug.
Haben Sie Lücken in Ihrer 'id' Spalte? –
@PaulSpiegel Ja, zum Beispiel ID: 1 wird als Lebensstil kategorisiert, ID: 2 wird als Unterhaltung kategorisiert, ID: 3 wird als Wissenschaft kategorisiert und so weiter. Wenn die Abfrage alle Unterhaltungskategorien erfasst, sind alle diese IDs Nummern mit Lücken zwischen ihnen. – user2896120