2016-09-07 7 views
0

데이터를 각 그룹에서 첫 번째, 마지막, 최대, 최소로 가져 오는 작업이 있습니다. 내 솔루션은 작동하지만 테이블의 행 수가 약 5 천만이기 때문에 매우 느립니다.그룹의 마지막 값과 첫 번째 값

내가이 쿼리의 성능을 향상시킬 수있는 방법 :

SELECT 
    date_trunc('minute', t_ordered."timestamp"), 
    MIN (t_ordered.price), 
    MAX (t_ordered.price), 
    FIRST (t_ordered.price), 
    LAST (t_ordered.price) 
FROM(
    SELECT t.price, t."timestamp" 
    FROM trade t 
    WHERE t."timestamp" >= '2016-01-01' AND t."timestamp" < '2016-09-01' 
    ORDER BY t."timestamp" ASC 
) t_ordered 
GROUP BY 1 
ORDER BY 1 

이 처음이자 마지막이 from postgresql wiki

타임 스탬프 열이 인덱스 집계 함수됩니다. 설명 (상세 분석) :

GroupAggregate (cost=13112830.84..33300949.59 rows=351556 width=14) (actual time=229538.092..468212.450 rows=351138 loops=1) 
    Output: (date_trunc('minute'::text, t_ordered."timestamp")), min(t_ordered.price), max(t_ordered.price), first(t_ordered.price), last(t_ordered.price) 
     Group Key: (date_trunc('minute'::text, t_ordered."timestamp")) 
     -> Sort (cost=13112830.84..13211770.66 rows=39575930 width=14) (actual time=229515.281..242472.677 rows=38721704 loops=1) 
     Output: (date_trunc('minute'::text, t_ordered."timestamp")), t_ordered.price 
     Sort Key: (date_trunc('minute'::text, t_ordered."timestamp")) 
     Sort Method: external sort Disk: 932656kB 
     -> Subquery Scan on t_ordered (cost=6848734.55..7442373.50 rows=39575930 width=14) (actual time=102166.368..155540.492 rows=38721704 loops=1) 
      Output: date_trunc('minute'::text, t_ordered."timestamp"), t_ordered.price 
      -> Sort (cost=6848734.55..6947674.38 rows=39575930 width=14) (actual time=102165.836..130971.804 rows=38721704 loops=1) 
       Output: t.price, t."timestamp" 
       Sort Key: t."timestamp" 
       Sort Method: external merge Disk: 993480kB 
       -> Seq Scan on public.trade t (cost=0.00..1178277.21 rows=39575930 width=14) (actual time=0.055..25726.038 rows=38721704 loops=1) 
         Output: t.price, t."timestamp" 
         Filter: ((t."timestamp" >= '2016-01-01 00:00:00'::timestamp without time zone) AND (t."timestamp" < '2016-09-01 00:00:00'::timestamp without time zone)) 
         Rows Removed by Filter: 9666450 
Planning time: 1.663 ms 
Execution time: 468949.753 ms 

어쩌면 그것은 윈도우 기능을 수행 할 수 있습니까? 나는 시도하지만 난 종류를 만들기 그들에게

+0

내부 쿼리의 성능 및 행 수는 얼마입니까? –

+0

하위 쿼리에서'first()','last()'및'order by'를 제거하면 성능이 어떻게됩니까? –

+0

하위 쿼리 쿼리의 행 개수는 약 600 만입니다 – LifeIsGoodMF

답변

1

을 사용하기에 충분한 지식이없는 적절한 집계 잘하면 더 잘 작동합니다 :

create type tp as (timestamp timestamp, price int); 

create or replace function min_tp (tp, tp) 
returns tp as $$ 
    select least($1, $2); 
$$ language sql immutable; 

create aggregate min (tp) (
    sfunc = min_tp, 
    stype = tp 
); 

minmax (목록에없는) 집계 함수가 쿼리를 줄일 수 단일 루프 :

select 
    date_trunc('minute', timestamp) as minute, 
    min (price) as price_min, 
    max (price) as price_max, 
    (min ((timestamp, price)::tp)).price as first, 
    (max ((timestamp, price)::tp)).price as last 
from t 
where timestamp >= '2016-01-01' and timestamp < '2016-09-01' 
group by 1 
order by 1 

이 (상세 분석) 설명 :

GroupAggregate (cost=6954022.61..27159050.82 rows=287533 width=14) (actual time=129286.817..510119.582 rows=351138 loops=1) 
    Output: (date_trunc('minute'::text, "timestamp")), min(price), max(price), (min(ROW("timestamp", price)::tp)).price, (max(ROW("timestamp", price)::tp)).price 
    Group Key: (date_trunc('minute'::text, trade."timestamp")) 
    -> Sort (cost=6954022.61..7053049.25 rows=39610655 width=14) (actual time=129232.165..156277.718 rows=38721704 loops=1) 
     Output: (date_trunc('minute'::text, "timestamp")), price, "timestamp" 
     Sort Key: (date_trunc('minute'::text, trade."timestamp")) 
     Sort Method: external merge Disk: 1296392kB 
     -> Seq Scan on public.trade (cost=0.00..1278337.71 rows=39610655 width=14) (actual time=0.035..45335.947 rows=38721704 loops=1) 
      Output: date_trunc('minute'::text, "timestamp"), price, "timestamp" 
      Filter: ((trade."timestamp" >= '2016-01-01 00:00:00'::timestamp without time zone) AND (trade."timestamp" < '2016-09-01 00:00:00'::timestamp without time zone)) 
      Rows Removed by Filter: 9708857 
Planning time: 0.286 ms 
Execution time: 510648.395 ms 
+0

감사합니다. 어떻게 Postgres가'Sort Method : external merge Disk : 1296392kB'를 메모리에 만들까요? – LifeIsGoodMF

+0

@ user2500146'postgresql.conf'의'work_mem' 값을 확인하십시오. 인덱스 테스트'create index minute on t (date_trunc ('minute', timestamp))' –

관련 문제