我想在PostgreSQL中随机选择行,我尝试了以下代码:
select * from table where random() < 0.01;
但是其他人建议这样做:
select * from table order by random() limit 1000;
我有一个有500万行的非常大的表格,我希望它运行速度很快。
哪种方法更好?它们之间有什么差异?选择随机行的最佳方法是什么?
我想在PostgreSQL中随机选择行,我尝试了以下代码:
select * from table where random() < 0.01;
但是其他人建议这样做:
select * from table order by random() limit 1000;
我有一个有500万行的非常大的表格,我希望它运行速度很快。
哪种方法更好?它们之间有什么差异?选择随机行的最佳方法是什么?
used
的布尔列。id_values id | used
----+--------
1 | FALSE
2 | FALSE
3 | FALSE
4 | FALSE
5 | FALSE
...
ID_VALUES
表。然后,按照 Erwin 的描述,创建一个材料化视图,对 ID_VALUES
表进行随机排序:CREATE MATERIALIZED VIEW id_values_randomized AS
SELECT id
FROM id_values
ORDER BY random();
UPDATE id_values
SET used = TRUE
WHERE id_values.id IN
(SELECT i.id
FROM id_values_randomized r INNER JOIN id_values i ON i.id = r.id
WHERE (NOT i.used)
LIMIT 1)
RETURNING id;
LIMIT
-- 如果您需要一次获取多个随机值,请将LIMIT
更改为所需值的数量n
。id_values
上有适当的索引,我相信UPDATE-RETURNING应该非常快速地执行,负载很小。它通过一个数据库往返返回随机值。 "可用"行的标准可以是任意复杂的条件。可以随时向id_values
表中添加新行,并且只要刷新物化视图(可能可以在非高峰时间运行),它们就会变得可访问。物化视图的创建和刷新将很慢,但只需要在需要使新的ID可用于id_values
表时执行它。我知道我来晚了,但我刚刚发现了这个很棒的工具叫做pg_sample:
pg_sample
- 从一个较大的PostgreSQL数据库中提取一个小的样本数据集,同时保持引用完整性。
我尝试过在一个有350M行的数据库上使用它,速度非常快,不知道关于“随机性”怎么样。
./pg_sample --limit="small_table = *" --limit="large_table = 100000" -U postgres source_db | psql -U postgres target_db
添加一个名为r
的列,类型为serial
。索引r
。
假设我们有200,000行数据,我们将生成一个随机数n
,其中0 < n
<= 200,000。
选择r > n
的行,按ASC
排序并选择最小的一行。
代码:
select * from YOUR_TABLE
where r > (
select (
select reltuples::bigint AS estimate
from pg_class
where oid = 'public.YOUR_TABLE'::regclass) * random()
)
order by r asc limit(1);