Como faço para tirar uma amostra aleatória simples eficiente no SQL? O banco de dados em questão está executando o MySQL; minha mesa é pelo menos 200.000 linhas, e eu quero uma amostra aleatória simples de cerca de 10.000.
A resposta óbvio é:
SELECT * FROM table ORDER BY RAND() LIMIT 10000
Para grandes tabelas, que é muito lento: ele chama RAND () para cada linha (que já o coloca em O (n)), e classifica-los, tornando-O (n lg n) na melhor das hipóteses. Existe uma maneira de fazer isso mais rápido do que O (n)?
Nota : Como assinala Andrew Mao nos comentários, Se você estiver usando esta abordagem em SQL Server, você deve usar a função NEWID T-SQL (), porque RAND () pode retornar o mesmo valor para todas as linhas .
EDIT: 5 ANOS DEPOIS
Corri para este problema novamente com uma mesa maior, e acabou usando uma versão do @ solução de ignorante, com dois ajustes:
- Amostra as linhas a 2-5x meu tamanho da amostra desejada, para a ordem de forma barata, RAND ()
- Salve o resultado da RAND () para uma coluna indexada em cada insert / update. (Se o seu conjunto de dados não é muito update-pesado, você pode precisar de encontrar outra maneira de manter esta coluna fresco.)
Para ter uma amostra de 1000 peça de uma mesa, eu conto as linhas e provar o resultado para baixo para, em média, 10.000 linhas com a coluna frozen_rand:
SELECT COUNT(*) FROM table; -- Use this to determine rand_low and rand_high
SELECT *
FROM table
WHERE frozen_rand BETWEEN %(rand_low)s AND %(rand_high)s
ORDER BY RAND() LIMIT 1000
(Meu aplicação efectiva envolve mais trabalho para se certificar de que eu não undersample, e para envolver manualmente rand_high ao redor, mas a idéia básica é cortar aleatoriamente seu N até alguns milhares.)
Enquanto isso faz alguns sacrifícios, que me permite experimentar o banco de dados para baixo usando uma varredura de índice, até que é pequeno o suficiente para ORDER BY RAND () novamente.













