ORDER BY RAND()
jest powolny, ponieważ DBMS musi czytać wszystkie wiersze, sortować je wszystkie, aby zachować tylko kilka wierszy. Tak więc wydajność tego zapytania w dużym stopniu zależy od liczby wierszy w tabeli i spada wraz ze wzrostem liczby wierszy.
Nie ma sposobu, aby to zoptymalizować.
Istnieją jednak alternatywy:
Możesz zaimplementować „uzyskaj 5 losowych wierszy” wykonując 6 zapytań:
- pobierz liczbę wierszy w tabeli (możesz buforować ten jeden)
-
wykonaj 5 zapytań z
OFFSET <random offset from 0 to $number_of_rows-1> LIMIT 1
(tj. odczytaj i zwróć tylko jeden wiersz z jakiegoś losowego przesunięcia)Na przykład:
SELECT * FROM Products OFFSET 42 LIMIT 1
(uwaga:na razie bez dołączania)Takie zapytania są bardzo szybkie i działają w czasie praktycznie niezależnym od rozmiaru tabeli.
Powinno to być dużo szybciej niż ORDER BY RAND()
.
Teraz, aby uzyskać losowy obraz dla każdego losowego produktu:
SELECT *
FROM (
SELECT *
FROM Products
OFFSET 42 LIMIT 1
) p
JOIN ProductImages pi
ON pi.product_id = p.id
ORDER BY RAND()
LIMIT 1
Zapytanie wewnętrzne jest nadal szybkie, a zewnętrzne sortuje tylko kilka wierszy (zakładając, że jest kilka obrazów na produkt), więc nadal może używać zamówienia przez rand().