2014-07-05 3 views
0

Я пытаюсь проверить распределение чисел в столбце таблицы. Вместо того, чтобы вычислять всю таблицу (которая является большой - десятки гигабайт), я хочу оценить с помощью повторной выборки. Я думаю, что типичный метод Postgres для этогоЭффективная повторная выборка с заменой таблицы в PostgreSQL?

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

, но это медленно для повторной выборки, тем более, что (я подозреваю) манипулирует весь столбец каждый раз, когда я запускаю его.

Есть ли лучший способ?

EDIT: Просто чтобы убедиться, что я выразил это правильно, я хочу сделать следующее:

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

без Переупорядочьте Целые массивный стол каждый раз. Возможно, я мог бы получить все идентификаторы строк таблицы и образец из него в R или что-то еще, а затем просто запросить эти строки?

+0

В SQL2003 положение о TABLESAMPLE, где введена (DB2 реализовала его, не уверен если есть другие). Это обсуждалось (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 как строки в таблице не сортируются (особенно если они обновляются часто), это должно дать вам «случайный» образец. Но вы правы: если вы запустите его дважды, вы, скорее всего, получите те же строки. Но вы _can_ все еще используете '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

Смежные вопросы