如何在超多数据里随机高效地捞点数据?

本文将以PG库为例,介绍几种随机捞取数据的方式,各有优劣,按需使用

1. tablesample
"TABLESAMPLE 是 PostgreSQL 提供的一种抽样方法,使用伯努利抽样方法,例如从表中抽取约 20000 条数据。请注意,实际抽取的数据量可能略有不同,因为抽样过程是随机的。

//如果表中有 1 亿条数据,您想要抽取 20000 条数据,
//那么抽样百分比为 0.02%(20000 / 100000000 * 100)
SELECT * FROM your_table_name TABLESAMPLE BERNOULLI(0.02) LIMIT 20000
          

2. citd
使用ctid进行抽样, PostgreSQL中的ctid(元组ID)是一个特殊的列,可以用于唯一标识表中的一行。ctid由块编号和索引元组编号组成,因此它们在表中是顺序排列的,所欲可以使用ctid来抽取数据,如下所示:

//首先,估算表中的行数。这可以通过查询`pg_class`表来完成:
SELECT reltuples::bigint AS estimate FROM pg_class WHERE relname='your_table_name';
//这将返回一个估算值,表示表中的行数。
//计算步长,使用估算的行数除以要抽取的数据量,计算步长。
//例如,如果估算的行数为100000000(1亿),并且您想要抽取20000条数据,那么步长为5000(100000000 / 20000)
SELECT * FROM your_table_name WHERE ctid IN (SELECT ctid  FROM your_table_name
WHERE ctid % 5000 = 0 -- 步长为5000  
LIMIT 20000);  
//这将返回大约20000条数据。请注意,这种方法的随机性可能较低,因为它依赖于表中数据的物理存储顺序。另外,这种方法在数据删除或更新后可能会导致不准确的结果,因为`ctid`在这些操作后可能会发生变化。在这种情况下,您可以考虑使用主键或其他唯一标识符来代替`ctid`。       

3. 分桶
将数据分成 1000 个桶,并从每个桶中抽取前 20 条数据

//使用 `NTILE()` 函数将数据分成 1000 个桶,并为每个桶分配一个 `bucket_id`:
CREATE TEMPORARY TABLE table2 AS SELECT *, NTILE(1000) OVER (ORDER BY RANDOM()) AS bucket_id
FROM table1;
// 使用 `ROW_NUMBER()` 函数计算每个桶中数据的行号,并将结果存储在临时表 `table3` 中:
CREATE TEMPORARY TABLE table3 AS SELECT *, ROW_NUMBER() OVER (PARTITION BY bucket_id) AS row_num 
FROM table2;
// 从 `table3` 中选择 `row_num` 小于等于 20 的数据,即从每个桶中抽取前 20 条数据:
SELECT * FROM table3 WHERE row_num <= 20;
         

4. offset
首先对表中的数据进行排序(可以根据需要更改排序列),然后计算每行的行号。然后,选择行号能被 5000 整除的行。最后,使用 LIMIT 语句限制结果的行数

SELECT * FROM 
(SELECT *, ROW_NUMBER() OVER (ORDER BY column_name) as rn FROM your_table_name) t WHERE rn % 5000 = 0
LIMIT 20000;

当然还有别的类型的方法,目前推荐citd、tablesample以及分桶;citd和tablesample方法较快,但citd随机性一般,tablesample方法速度理论最快,但抽取的数量不一定精确;其次使用分桶的方法,随机性较好和数量精确,能够支持更复杂的抽样方法,但是速度并不一定是最优的。大家按需使用就好。

  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值