如何在 SQL 中获取高效的简单随机样本?有问题的数据库正在运行 MySQL; 我的表至少有200,000行,我想要一个大约10,000行的简单随机样本。
“显而易见”的答案是:
SELECT * FROM table ORDER BY RAND() LIMIT 10000
For large tables, that's too slow: it calls RAND()
for every row (which already puts it at O(n)), and sorts them, making it O(n lg n) at best. Is there a way to do this faster than O(n)?
注意 : 正如 Andrew Mao 在注释中指出的,如果您在 SQL Server 上使用这种方法,那么您应该使用 T-SQL 函数 NEWID()
,因为 RAND () 可以为所有行返回相同的值。
5年后
我用一个更大的桌子再次遇到了这个问题,最后使用了一个@际无知的解决方案,并做了两个调整:
ORDER BY RAND()
RAND()
的结果保存到一个索引列。(如果您的数据集不是很多更新,那么您可能需要找到另一种方法来保持这个列的新鲜度。)为了获取一个包含1000个条目的表示例,我对这些行进行计数,然后对结果进行取样,平均为10,000行,其中包含 zen _ 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
(我的实际实现需要做更多的工作,以确保我不会样本不足,并手动包装 rand _ high,但基本思想是“随机把 N 减少到几千。”)
虽然这做出了一些牺牲,但它允许我使用索引扫描对数据库进行取样,直到数据库小到足以再次使用 ORDER BY RAND()
。