2014-07-05 50 views
0

我試圖檢查一列表中的數字分佈。我不想在整個表上計算(這很大 - 幾十千兆字節),我想通過重複採樣來估計。我覺得這個典型的Postgres的方法是用PostgreSQL中的表替換有效的重複採樣?

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

但這是重複採樣慢,特別是因爲(我懷疑),它操縱我每次運行它時整列。

有沒有更好的方法?

編輯:只是爲了確保我表達是正確的,我要做到以下幾點:無需每次重新排序整個龐大的表

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

。也許我可以得到所有的錶行ID,並在R或其他東西中取樣,然後請求這些行?

+0

在SQL2003那裏介紹(DB2已經實現了它,不知道TABLESAMPLE子句如果有其他人)。它已被討論(https://wiki.postgresql.org/index.php?title=TABLESAMPLE_Implementation&action=history)postgres,但我不知道目前的狀態。 – Lennart

回答

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')) 
; 
+0

但是,在100行的表中,50%的樣本會給我行1:50,而20%的樣本會給我行1:20,否則情況不會如此嗎?我的目標是能夠進行多次獨立抽籤。 –

+0

@PatrickMcCarthy作爲表中的行不排序(特別是如果它們經常更新)它應該給你一個「隨機」樣本。但是你是對的:如果你運行兩次,你很可能會得到相同的行。但是你仍然可以使用'order by random()',但是它會使查詢非常慢,因爲它總是讀整個表。 –

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