我想在PostgreSQL中随机选择行,我尝试了这个:
select * from table where random() < 0.01;
但也有人建议:
select * from table order by random() limit 1000;
我有一个非常大的表,有5亿行,我希望它是快速的。
哪种方法更好?有什么不同?选择随机行最好的方法是什么?
我想在PostgreSQL中随机选择行,我尝试了这个:
select * from table where random() < 0.01;
但也有人建议:
select * from table order by random() limit 1000;
我有一个非常大的表,有5亿行,我希望它是快速的。
哪种方法更好?有什么不同?选择随机行最好的方法是什么?
当前回答
ORDER BY的那个会比较慢。
Select * from table where random() < 0.01;逐条记录,然后决定是否随机过滤。这将是O(N)因为它只需要检查每个记录一次。
Select * from table order by random() limit 1000;将对整个表进行排序,然后选择前1000个。除去幕后的巫毒魔法,顺序是O(N * log N)。
random() < 0.01的缺点是,输出记录的数量是可变的。
注意,有一种比随机排序更好的方法来打乱一组数据:Fisher-Yates Shuffle,它在O(N)中运行。不过,在SQL中实现shuffle听起来很有挑战性。
其他回答
ORDER BY的那个会比较慢。
Select * from table where random() < 0.01;逐条记录,然后决定是否随机过滤。这将是O(N)因为它只需要检查每个记录一次。
Select * from table order by random() limit 1000;将对整个表进行排序,然后选择前1000个。除去幕后的巫毒魔法,顺序是O(N * log N)。
random() < 0.01的缺点是,输出记录的数量是可变的。
注意,有一种比随机排序更好的方法来打乱一组数据:Fisher-Yates Shuffle,它在O(N)中运行。不过,在SQL中实现shuffle听起来很有挑战性。
从PostgreSQL 9.5开始,有一个新的语法专门用于从表中获取随机元素:
SELECT * FROM mytable TABLESAMPLE SYSTEM (5);
这个例子将给出mytable中5%的元素。
有关文档的更多说明:http://www.postgresql.org/docs/current/static/sql-select.html
我知道我有点晚了,但我刚刚找到了这个叫做pg_sample的很棒的工具:
pg_sample -从较大的PostgreSQL数据库中提取一个小的样本数据集,同时保持引用完整性。
我尝试了一个350M行的数据库,它真的很快,不知道随机性。
./pg_sample --limit="small_table = *" --limit="large_table = 100000" -U postgres source_db | psql -U postgres target_db
您可以通过使用来检查和比较两者的执行计划
EXPLAIN select * from table where random() < 0.01;
EXPLAIN select * from table order by random() limit 1000;
对一个大型表1的快速测试表明,ORDER BY首先对整个表进行排序,然后选择前1000个项。对一个大表进行排序不仅要读取该表,还包括读取和写入临时文件。where random() < 0.1只扫描整个表一次。
对于大型表,这可能不是您想要的,因为即使是一次完整的表扫描也可能需要很长时间。
第三个建议是
select * from table where random() < 0.01 limit 1000;
这个方法在找到1000行后立即停止表扫描,因此返回得更快。当然,这将降低随机性,但也许这对于你来说已经足够好了。
编辑:除了这些考虑因素之外,你可以看看已经问过的问题。使用查询[postgresql]随机返回一些结果。
快速随机行选择在Postgres 如何从postgreSQL表检索随机数据行? Postgres:从表中获取随机条目-太慢
depez的一篇链接文章概述了更多的方法:
http://www.depesz.com/index.php/2007/09/16/my-thoughts-on-getting-random-row/
1“大”是指“完整的表将不适合内存”。
我认为在postgreSQL中最好和最简单的方法是:
SELECT * FROM tableName ORDER BY random() LIMIT 1