Como otimizar o operador ORDER BY RAND()?
sobes.tech IA
Resposta da IA
Otimizar ORDER BY RAND() é difícil, pois requer uma seleção completa de dados para gerar um número aleatório para cada linha. As abordagens típicas:
-
Seleção de um identificador aleatório:
- Obter o número de linhas na tabela.
- Gerar um número aleatório entre 0 e N-1 (ou 1 e N).
- Selecionar a linha com o deslocamento correspondente ou
OFFSET.
SELECT COUNT(*) FROM your_table; -- Assume-se que o total de linhas = N SELECT * FROM your_table LIMIT 1 OFFSET floor(random() * N);Este método é adequado para selecionar uma ou algumas linhas aleatórias. Não é eficiente para um grande número de linhas.
-
Seleção aleatória por intervalo de
id:- Encontrar o
idmínimo e máximo. - Gerar um número aleatório nesse intervalo.
- Selecionar a linha com
id >= número_aleatório, usandoLIMIT.
SELECT MIN(id), MAX(id) FROM your_table; -- Assume-se que min_id, max_id foram obtidos -- Na aplicação, gerar um id aleatório no intervalo [min_id, max_id] -- Por exemplo: id_aleatório = min_id + floor(random() * (max_id - min_id + 1)) SELECT * FROM your_table WHERE id >= id_aleatório LIMIT 1;Pode omitir linhas se houver lacunas em
id. - Encontrar o
-
Criação de uma tabela temporária ou uso de subconsulta com ordenação por número aleatório:
- Selecionar um subconjunto de dados ou apenas
idem uma subconsulta. - Aplicar
ORDER BY RAND()a esse subconjunto.
SELECT * FROM your_table AS t1 JOIN (SELECT id FROM your_table ORDER BY RAND() LIMIT 100) AS t2 ON t1.id = t2.id;Reduz a carga se
LIMITfor aplicado à subconsulta. - Selecionar um subconjunto de dados ou apenas
-
Uso de um campo adicional com número aleatório:
- Adicionar um campo na tabela para armazenar um número aleatório.
- Atualizar periodicamente esse campo para todas as linhas.
- Ordenar por esse campo.
-- Adicionar campo ALTER TABLE your_table ADD random_sort_key FLOAT; -- Atualização periódica UPDATE your_table SET random_sort_key = RAND(); -- Seleção SELECT * FROM your_table ORDER BY random_sort_key LIMIT 10;Requer alterações no esquema e no processo de atualização em segundo plano.
-
Algoritmo de "embaralhamento" (Fisher-Yates) fora do banco de dados:
- Selecionar todos os
id(ou todos os dados, se forem pequenos). - Embaralhar a lista na aplicação.
- Selecionar os primeiros N elementos.
// Assume-se que ids é []int // ids = ... // Obter ids do banco de dados rand.Shuffle(len(ids), func(i, j int) { ids[i], ids[j] = ids[j], ids[i] }) // Agora os primeiros N elementos de ids são aleatórios // Podem ser usados para selecionar linhas completas // SELECT * FROM your_table WHERE id IN (...)Adequado apenas para tabelas com poucas linhas.
- Selecionar todos os
A escolha do método ótimo depende do tamanho da tabela, do número de linhas aleatórias necessárias e do sistema de gerenciamento de banco de dados específico. Para a maioria dos casos, quando é necessário selecionar um pequeno número de linhas aleatórias de uma tabela grande, a combinação de obter os id com um OFFSET ou WHERE id IN (...) será mais eficiente do que ordenar por RAND() diretamente.