ORDER BY RAND()
е бавен, защото СУБД трябва да прочете всички редове, да ги сортира всички, само за да запази само няколко реда. Така че производителността на тази заявка силно зависи от броя на редовете в таблицата и намалява с увеличаването на броя на редовете.
Няма начин да се оптимизира това.
Има обаче алтернативи:
Можете да приложите "вземете 5 произволни реда" като направите 6 заявки:
- вземете броя на редовете в таблицата (можете да кеширате този)
-
направете 5 заявки с
OFFSET <random offset from 0 to $number_of_rows-1> LIMIT 1
(т.е. чете и връща само един ред от произволно отместване)Например:
SELECT * FROM Products OFFSET 42 LIMIT 1
(забележка:без присъединяване, засега)Такива заявки са много бързи и се изпълняват за време, практически независимо от размера на таблицата.
Това трябва да е много по-бързо от ORDER BY RAND()
.
Сега, за да получите произволно изображение за всеки произволен продукт:
SELECT *
FROM (
SELECT *
FROM Products
OFFSET 42 LIMIT 1
) p
JOIN ProductImages pi
ON pi.product_id = p.id
ORDER BY RAND()
LIMIT 1
Вътрешната заявка все още е бърза, а външната сортира само няколко реда (ако приемем, че има малко изображения на продукт) и така все още може да използва подреждане по rand().