SELECT * FROM my_table TABLESAMPLE SYSTEM(0.000001) LIMIT 1;
-- if you got no result:
SELECT * FROM my_table TABLESAMPLE SYSTEM(0.00001) LIMIT 1;
-- if you got no result:
SELECT * FROM my_table TABLESAMPLE SYSTEM(0.0001) LIMIT 1;
-- if you got no result:
SELECT * FROM my_table TABLESAMPLE SYSTEM(0.001) LIMIT 1;
...
这篇(很)长的文章摘要如下。 作者列举了四种方法: 1)ORDER BY random() LIMIT 1;--慢速 2)ORDER BY id where id>=random()*N LIMIT 1-如果有间隙,则为非均匀 3)随机列--需要不时更新 4)自定义random aggregate--巧妙的方法,可能很慢:random()需要生成N次 并建议通过使用以下方法改进方法#2 5)ORDER BY id where id=random()*N LIMIT 1,如果结果为空,则执行后续重新查询。
create table randtest (id serial primary key, data int not null);
insert into randtest (data) select (random()*1000000)::int from generate_series(1,1000000);
create index randtest_md5_id_idx on randtest (md5(id::text));
explain analyze
select * from randtest where md5(id::text)>md5(random()::text)
order by md5(id::text) limit 1;
结果:
Limit (cost=0.42..0.68 rows=1 width=8) (actual time=6.219..6.220 rows=1 loops=1)
-> Index Scan using randtest_md5_id_idx on randtest (cost=0.42..84040.42 rows=333333 width=8) (actual time=6.217..6.217 rows=1 loops=1)
Filter: (md5((id)::text) > md5((random())::text))
Rows Removed by Filter: 1831
Total runtime: 6.245 ms
SELECT * FROM
(
(SELECT id, random FROM t where <condition> and random >= 0.27 ORDER BY random LIMIT 1)
UNION ALL
(SELECT id, random FROM t where <condition> and random < 0.27 ORDER BY random DESC LIMIT 1)
) as results
ORDER BY abs(0.27-random) LIMIT 1;
(查询取自here) 如果在条件行和随机行(包含随机数)上有一个索引,那么在这个850万行的表上,我会在6毫秒内得到一个结果,这比使用order by random()之类的方法快了几个数量级。 为了提高随机性,您还可以为您命中的每个结果生成一个新的随机数。(如果不这样做,某些数字将比其他数字出现得更频繁。) 与TABLESAMPLE不同,它还支持条件。
8条答案
按热度按时间x4shl7ld1#
您可能希望尝试使用
OFFSET
,例如N
是mytable
中的行数。您可能需要首先执行SELECT COUNT(*)
以计算N
的值。更新(安东尼哈奇金斯)
必须在此处使用
floor
:考虑一个2行的表;
random()*N
生成0 <= x < 2
,例如SELECT myid FROM mytable OFFSET 1.7 LIMIT 1;
返回0行,因为隐式舍入到最接近的整数。4nkexdtk2#
PostgreSQL 9.5引入了一种新的方法,可以更快地选择样本:TABLESAMPLE
语法为
如果您只想选择一行,这不是最佳解决方案,因为您需要知道表的COUNT才能计算准确的百分比。
要避免慢速COUNT并对从1行到数十亿行的表使用快速TABLESAMPLE,可以执行以下操作:
这可能看起来不那么优雅,但可能比其他任何答案都要快。
要决定是否使用BERNULLI或SYSTEM,请阅读http://blog.2ndquadrant.com/tablesample-in-postgresql-9-5-2/上的差异
ezykj2lf3#
我用一个子查询试过了,效果很好。偏移,至少在Postgresql v8. 4. 4中效果很好。
5lhxktic4#
您需要使用
floor
:8ulbf1ek5#
查看此链接了解一些不同的选项。http://www.depesz.com/index.php/2007/09/16/my-thoughts-on-getting-random-row/
最新情况:(A.Hatchkins)
这篇(很)长的文章摘要如下。
作者列举了四种方法:
1)
ORDER BY random() LIMIT 1;
--慢速2)
ORDER BY id where id>=random()*N LIMIT 1
-如果有间隙,则为非均匀3)随机列--需要不时更新
4)自定义random aggregate--巧妙的方法,可能很慢:random()需要生成N次
并建议通过使用以下方法改进方法#2
5)
ORDER BY id where id=random()*N LIMIT 1
,如果结果为空,则执行后续重新查询。webghufk6#
获取随机行最简单、最快的方法是使用
tsm_system_rows
扩展:然后可以选择所需的确切行数:
PostgreSQL 9.5及更高版本提供此功能。
参见:https://www.postgresql.org/docs/current/static/tsm-system-rows.html
eivnm1vs7#
我已经想出了一个不需要
TABLESAMPLE
的快速解决方案,比OFFSET random()*N LIMIT 1
快得多,甚至不需要计算表数。其思想是使用随机但可预测的数据创建表达式索引,例如
md5(primary key)
。下面是使用1 M行样本数据进行的测试:
结果:
此查询有时可能(概率约为1/Number_of_rows)返回0行,因此需要检查并重新运行。而且概率并不完全相同-某些行比其他行更可能。
比较:
型
结果差异很大,但可能相当糟糕:
wgxvkvu98#
我向每一行添加了一个随机生成的数字,并在我的编程语言中生成一个添加到每一行的随机数。调用时,我将一个随机数传递给查询(在本例中为0. 27)
(查询取自here)
如果在条件行和随机行(包含随机数)上有一个索引,那么在这个850万行的表上,我会在6毫秒内得到一个结果,这比使用order by random()之类的方法快了几个数量级。
为了提高随机性,您还可以为您命中的每个结果生成一个新的随机数。(如果不这样做,某些数字将比其他数字出现得更频繁。)
与TABLESAMPLE不同,它还支持条件。