在PostgreSQL中替换表格的高效重复采样?

时间:2014-07-05 03:35:21

标签: sql postgresql resampling

我试图检查表格列中的数字分布。我想通过重复采样来估算整个表(大到几十千兆字节)而不是计算。我认为典型的Postgres方法是

select COLUMN
from TABLE
order by RANDOM()
limit 1;

但这对于重复采样来说很慢,特别是因为(我怀疑)它每次运行时都会操纵整个列。

有更好的方法吗?

编辑:为了确保我表达正确,我想做以下事情:

for(i in 1:numSamples)
  draw 500 random rows
end

每次都不必重新排序整个大表。也许我可以在R或其他东西中获取所有表行ID和样本,然后只是请求那些行?

2 个答案:

答案 0 :(得分:0)

如果你想要一个数据样本,那么使用表的估计大小然后计算一个百分比作为样本呢?

pg_class存储每个表的行数的估计值(如果我没有弄错的话,由真空过程更新)。

因此,以下内容将从该表中选择所有行的1%:

with estimated_rows as (
  select reltuples as num_rows
  from pg_class t
    join pg_namespace n on n.oid = t.relnamespace
  where t.relname = 'some_table'
  and n.nspname = 'public'
)
select *
from some_table
limit (select 0.01 * num_rows from estimated_rows)
; 

如果你经常这样做,你可能想要创建一个函数,所以你可以做这样的事情:

select *
from some_table
limit (select estimate_percent(0.01, 'public', 'some_table'))
; 

答案 1 :(得分:0)

从目标表创建一个临时表,添加行号列

drop table if exists temp_t;
create temporary table temp_t as
select *, (row_number() over())::int as rn
from t

通过仅选择将在采样和过滤中使用的列来创建更轻的临时表。

按行号列

对其进行索引
create index temp_t_rn on temp_t(rn);
analyze temp_t;

为每个样本发出此查询

with r as (
    select ceiling(random() * (select max(rn) from temp_t))::int as rn
    from generate_series(1, 500) s
)
select *
from temp_t
where rn in (select rn from r)

SQL Fiddle