ORDER BY RAND()
é lento porque o DBMS tem que ler todas as linhas, ordenar todas, apenas para manter apenas algumas linhas. Portanto, o desempenho dessa consulta depende muito do número de linhas na tabela e diminui à medida que o número de linhas aumenta. Não há como otimizar isso.
Existem alternativas, no entanto:
Você pode implementar "obter 5 linhas aleatórias" fazendo 6 consultas:
- obtenha o número de linhas na tabela (você pode armazenar esta em cache)
-
faça 5 consultas comOFFSET <random offset from 0 to $number_of_rows-1> LIMIT 1
(ou seja, ler e retornar apenas uma linha de algum deslocamento aleatório)
Por exemplo:SELECT * FROM Products OFFSET 42 LIMIT 1
(nota:sem aderir, por enquanto)
Tais consultas são muito rápidas e executadas em um tempo praticamente independente do tamanho da tabela.
Isso deve ser muito mais rápido que
ORDER BY RAND()
. Agora, para obter uma imagem aleatória para cada produto aleatório:
SELECT *
FROM (
SELECT *
FROM Products
OFFSET 42 LIMIT 1
) p
JOIN ProductImages pi
ON pi.product_id = p.id
ORDER BY RAND()
LIMIT 1
A consulta interna ainda é rápida e a externa está classificando apenas algumas linhas (supondo que haja poucas imagens por produto) e, portanto, ainda pode usar a ordem por rand().