postgresql如何从表中高效的随机获取一条记录

select C_BH from db_scld.t_scld_cprscjl  order by `random()` LIMIT 1;
select c_jdrybm from db_scld.t_jdry
where c_bmbm = v_scdd and c_sfyx ='1' and c_ryzszt not in ('05','12','11','07','09','13') order by `random()` limit 1 db_jdsjpt=# explain analyze select C_BH from db_scld.t_scld_cprscjl order by random() LIMIT 1;
QUERY PLAN
---------------------------------------------------------------------------------------------------
Limit (cost=61029.94..61029.94 rows=1 width=41) (actual time=587.193..587.193 rows=1 loops=1)
-> Sort (cost=61029.94..63172.22 rows=856911 width=41) (actual time=587.185..587.185 rows=1 loops=1)
Sort Key: (random())
Sort Method: top-N heapsort Memory: 25kB
-> Seq Scan on t_scld_cprscjl (cost=0.00..56745.39 rows=856911 width=41) (actual time=0.019..380.139 rows=854682 loop
s=1)
Planning time: 1.179 ms
Execution time: 587.242 ms
(7 rows)
--表总数量
db_jdsjpt=# select count(*) from db_scld.t_scld_cprscjl;
count
--------
854682
(1 row)

随机获取一条记录random()

random()耗时:Time: 389.818 ms

--随机获取一条耗时
db_jdsjpt=# select C_BH from db_scld.t_scld_cprscjl order by random() LIMIT 1;
c_bh
----------------------------------
6d861b011c854040bf5b731f49d40b48
(1 row) Time: 389.818 ms

改写1

offset耗时:Time: 60.022 ms

--offset可以走索引,少了排序操作
db_jdsjpt=# select C_BH from db_scld.t_scld_cprscjl offset floor(random()*854682) LIMIT 1;
c_bh
----------------------------------
f90301bd8ac2485196ffae32ee70345c
(1 row) Time: 60.022 ms db_jdsjpt=# explain analyze select C_BH from db_scld.t_scld_cprscjl offset floor(random()*854682) LIMIT 1;
QUERY PLAN ---------------------------------------------------------------------------------------------------
Limit (cost=3747.64..3747.68 rows=1 width=33) (actual time=30.758..30.759 rows=1 loops=1)
-> Index Only Scan using i_corscjl_cprscbh_ on t_scld_cprscjl (cost=0.42..37472.65 rows=854682 width=33) (actual time=0.
047..25.808 rows=81993 loops=1)
Heap Fetches: 0
Planning time: 0.228 ms
Execution time: 30.802 ms
(5 rows) Time: 31.779 ms

改写2

pg从9.5开始提供抽样函数

使用tablesample抽样的过程中比例不能太低,否则可能获取不到结果,且不能带有过滤条件

system耗时: Time: 0.639 ms

system:随机性较差,效率高

--改写后耗时
db_jdsjpt=# select c_bh from db_scld.t_scld_cprscjl tablesample system(0.1) limit 1;
c_bh
----------------------------------
e2fce25399db42f0bf49faf8e7214d5f
(1 row) Time: 0.639 ms --system随机抽样以块为单位所以更快
db_jdsjpt=# explain analyze select c_bh from db_scld.t_scld_cprscjl tablesample system(0.1) limit 1;
QUERY PLAN
---------------------------------------------------------------------------------------------------
Limit (cost=0.00..0.23 rows=1 width=33) (actual time=0.105..0.105 rows=1 loops=1)
-> Sample Scan on t_scld_cprscjl (cost=0.00..192.55 rows=855 width=33) (actual time=0.102..0.102 rows=1 loops=1)
Sampling: system ('0.1'::real)
Planning time: 0.190 ms
Execution time: 0.134 ms
(5 rows) Time: 1.182 ms

改写3

bernoulli:随机性更好,但效率比system要低

bernoullih耗时:Time: 0.822 ms


db_jdsjpt=# select c_bh from db_scld.t_scld_cprscjl tablesample bernoulli(0.1) limit 1;
c_bh
----------------------------------
7ec30761ffd04bd9ad77797a33645a84
(1 row) Time: 0.822 ms --bernoulli以行为单位进行抽样,比system效率低点
db_jdsjpt=# explain analyze select c_bh from db_scld.t_scld_cprscjl tablesample bernoulli(0.1) limit 1;
QUERY PLAN
---------------------------------------------------------------------------------------------------
Limit (cost=0.00..53.85 rows=1 width=33) (actual time=1.410..1.411 rows=1 loops=1)
-> Sample Scan on t_scld_cprscjl (cost=0.00..46042.55 rows=855 width=33) (actual time=1.408..1.408 rows=1 loops=1)
Sampling: bernoulli ('0.1'::real)
Planning time: 0.446 ms
Execution time: 1.436 ms
(5 rows) Time: 25.770 ms

同理另外一条sql也可用同样的方式,且在c_bmbm字段上面加上索引

当有条件的时候可以使用offset获取,offset的值也可以通过for循环传入

db_jdsjpt=# select count(*) from db_scld.t_jdry;
count
--------
214819
(1 row) db_jdsjpt=# select c_jdrybm from db_scld.t_jdry where c_bmbm = '4402222804' and c_sfyx ='1' and c_ryzszt not in ('05','12','11','07','09','13') offset floor(random()*214819) limit 1;
c_jdrybm
----------
(0 rows) Time: 1.924 ms

对比

方法 耗时
order by random() 389.818 ms
offset n 60.022 ms-240ms
system() 0.639 ms
bernoulli() 0.822 ms

使用offset的时候和n的大小有关系,当n越大,扫描的索引块越多,就越大,但是相对于order by random()的方式仍然要快。

注意

system(0.1)等于百分之零点一,也就是抽样千分之一 854682*0.001=854,大概每次抽取854条记录

--system
db_jdsjpt=# select count(*) from db_scld.t_scld_cprscjl tablesample system(0.1) ;
count
-------
592
(1 row) Time: 1.499 ms --bernoulli
db_jdsjpt=# select count(*) from db_scld.t_scld_cprscjl tablesample bernoulli(0.1) ;
count
-------
840
(1 row) Time: 86.037 ms
这里可以看出bernoulli效率比system要低

结语

1.随机获取表中的一条数据,当表中数据较小时使用random感觉不明显,当数据量大时random由于每次都需要排序操作,导致随机获取一条的成本较高

4.随机获取一条记录可以使用limit 1 offset n-1的方式,或者使用随机抽样的方式

5.无论是使用limit 1 offset n还是使用tablesample随机抽样方式都需要知道表中的数据量,不能超过表数据量

postgresql-从表中随机获取一条记录的更多相关文章

  1. 从数据库表中随机获取N条记录的SQL语句

    Oracle: select * from (select * from tableName order by dbms_random.value) where rownum < N MS SQ ...

  2. 从mysql数据表中随机取出一条记录

    核心查找数据表代码: ; //此处的1就是取出数据的条数 但这样取数据网上有人说效率非常差的,那么要如何改进呢 搜索Google,网上基本上都是查询max(id) * rand()来随机获取数据. S ...

  3. 从表中随机返回n条记录

    创建测试用表: CREATE OR REPLACE VIEW V AS SELECT 'a' AS c FROM dual UNION ALL SELECT 'b' AS c FROM dual UN ...

  4. 1.10 从表中随机返回n条记录

    同时使用内置函数的rand函数. limit 和order by: select * from emp order by rand() limit 2;

  5. PHP如何实现在数据库随机获取几条记录

    本文实例讲述了PHP实现在数据库百万条数据中随机获取20条记录的方法.PHP实例分享给大家供大家参考,具体如下: 为什么要写这个? 在去某个公司面试时,让写个算法出来,当时就蒙了,我开发过程中用到算法 ...

  6. 转: 从Mysql某一表中随机读取n条数据的SQL查询语句

    若要在i ≤ R ≤ j 这个范围得到一个随机整数R ,需要用到表达式 FLOOR(i + RAND() * (j – i + 1)).例如, 若要在7 到 12 的范围(包括7和12)内得到一个随机 ...

  7. 从Mysql某一表中随机读取n条数据的SQL查询语句

    若要在i ≤ R ≤ j 这个范围得到一个随机整数R ,需要用到表达式 FLOOR(i + RAND() * (j – i + 1)).例如, 若要在7 到 12 的范围(包括7和12)内得到一个随机 ...

  8. 从数据表中随机抽取n条数据有哪几种方法(join实现可以先查数据然后再拼接)

    从数据表中随机抽取n条数据有哪几种方法(join实现可以先查数据然后再拼接) 一.总结 一句话总结:最好的是这个:"SELECT * FROM table WHERE id >= (( ...

  9. 【面经】面试官:如何以最高的效率从MySQL中随机查询一条记录?

    写在前面 MySQL数据库在互联网行业使用的比较多,有些小伙伴可能会认为MySQL数据库比较小,存储不了很多的数据.其实,这些小伙伴是真的不了解MySQL.MySQL的小不是说使用MySQL存储的数据 ...

随机推荐

  1. 在浏览器中输入URL后,执行的全部过程。会用到哪些协议?(一次完整的HTTP请求过程)

    在浏览器中输入URL后,执行的全部过程.会用到哪些协议?(一次完整的HTTP请求过程) 整个流程如下: 域名解析 为了将消息从你的PC上传到服务器上,需要用到IP协议.ARP协议和OSPF协议. 发起 ...

  2. python冒泡算法联系代码

    root@(none):~/python# python maopao.py[6, 11, 13, 22, 99]root@(none):~/python# cat maopao.py #!/usr/ ...

  3. 【Alpha冲刺阶段】Scrum Meeting Daily5

    [Alpha冲刺阶段]Scrum Meeting Daily5 1.会议简述 会议开展时间 2020/5/27 8:30-9:00 PM 会议基本内容摘要 大家讲述了自己的任务完成情况以及遇到的问题 ...

  4. 百度前端技术学院-基础-day2

    2020.9.15 今天是学习前端基础技术的第二天,今天制作了一个在线简历,纯html的那种.帮助我复习了以前的基础知识,也增加了新的知识点,比如制作列表可以用fieldset来整合数据. 我的在线简 ...

  5. 将ACCESS 的数据库中的表的文件 导出了EXCEL格式

    将ACCESS 的数据库中的表的文件 导出了EXCEL格式 '''' '将ACCESS数据库中的某个表的信息 导出为EXCEL 文件格式 'srcfName ACCESS 数据库文件路径 'desfN ...

  6. 我叫Mongo,干了「索引探索篇」提升我的效率,值得您拥有

    这是mongo第四篇"索引探索",后续会连续更新4篇 mongodb的文章总结上会有一系列的文章,顺序是先学会怎么用,在学会怎么用好,戒急戒躁,循序渐进,跟着我一起来探索交流.通过 ...

  7. 想用selenium ,先了解html 基础知识(5)

    二.HTML语法---了解!1.HTML超文本标记语言,是网页设计使用的语言.2.从<html>开始,到</html>结束,里面包括head和body两个部分,我们测试人员关心 ...

  8. css3选择器归类整理---基本选择器和属性选择器

    css3选择器分类 CSS3选择器分类如下图所示 选择器的语法 1.基本选择器 类型 代码 功能描述 通配选择器 *{ margin: 0; padding: 0; border: none; } 选 ...

  9. burpsuite无法拦截本地流量

    参考文章链接:https://blog.csdn.net/tb_youth/article/details/103436796?utm_medium=distribute.pc_relevant.no ...

  10. 如何使用Pytest进行自动化测试

    为什么需要自动化测试 自动化测试有很多优点,但这里有3个主要的点 可重用性:不需要总是编写新的脚本,除非必要,即使是新的操作系统版本也不需要编写脚本. 可靠性:人容易出错,机器不太可能.当运行不能跳过 ...