2017-05-12 13 views
1

私は最初にpostgresを使用していますが、それはむしろ最新のレコードを見つけようとしているのかどうか、そして現在動作しているかどうかにかかわらず、 これは私が思いついた最初のクエリです:DISTINCT ORDER BY非常に遅い

SELECT DISTINCT ON (device_id) c.device_id, c.timestamp, c.working 
     FROM call_logs c 
     ORDER BY c.device_id, c.timestamp desc 

そして、それは動作しますが、実行に時間に沿って取っています。

Unique (cost=94840.24..97370.54 rows=11 width=17) (actual time=424.424..556.253 rows=13 loops=1) 
    -> Sort (cost=94840.24..96105.39 rows=506061 width=17) (actual time=424.423..531.905 rows=506061 loops=1) 
    Sort Key: device_id, "timestamp" DESC 
    Sort Method: external merge Disk: 13272kB 
    -> Seq Scan on call_logs c (cost=0.00..36512.61 rows=506061 width=17) (actual time=0.059..162.932 rows=506061 loops=1) 
Planning time: 0.152 ms 
Execution time: 557.957 ms 
(7 rows) 

私は高速です以下が、非常に醜いを使用するクエリを更新しました:

SELECT c.device_id, c.timestamp, c.working FROM call_logs c 
    INNER JOIN (SELECT c.device_id, MAX(c.timestamp) AS timestamp 
               FROM call_logs c 
               GROUP BY c.device_id) 
               newest on newest.timestamp = c.timestamp 

と分析:

Nested Loop (cost=39043.34..39136.08 rows=12 width=17) (actual time=216.406..216.580 rows=15 loops=1) 
    -> HashAggregate (cost=39042.91..39043.02 rows=11 width=16) (actual time=216.347..216.351 rows=13 loops=1) 
    Group Key: c_1.device_id 
    -> Seq Scan on call_logs c_1 (cost=0.00..36512.61 rows=506061 width=16) (actual time=0.026..125.482 rows=506061 loops=1) 
    -> Index Scan using call_logs_timestamp on call_logs c (cost=0.42..8.44 rows=1 width=17) (actual time=0.016..0.016 rows=1 loops=13) 
    Index Cond: ("timestamp" = (max(c_1."timestamp"))) 
Planning time: 0.318 ms 
Execution time: 216.631 ms 
(8 rows) 

さえ、200msのは、私には少し遅いようです私が望むのは、デバイスごとのトップレコード(インデックス付きテーブルにあります)です。

これは私のインデックスですそれが使用されます。

CREATE INDEX call_logs_timestamp 
ON public.call_logs USING btree 
(timestamp) 
TABLESPACE pg_default; 

を、私は、インデックスの下に試してみましたが、全く役に立たない:

CREATE INDEX dev_ts_1 
ON public.call_logs USING btree 
(device_id, timestamp DESC, working) 
TABLESPACE pg_default; 

すべてのアイデアは、私が何かを明らかに不足しているのですか?

答えて

1

実際には500k行を通過するにはそれほど悪くありません。しかし、このクエリの場合:

call_logs(device_id, timestamp desc, working)のインデックスは最適なインデックスにする必要があります。同じインデックスのクエリを記述する

他の二つの方法があります。

select c.* 
from (select c.device_id, c.timestamp, c.working, c.*, 
      row_number() over (partition by device_id order by timestamp desc) as seqnum 
     from call_logs c 
    ) c 
where seqnum = 1; 

と:

select c.device_id, c.timestamp, c.working 
from call_logs c 
where not exists (select 1 
        from call_logs c2 
        where c2.device_id = c.device_id and 
         c2.timestamp > c.timestamp 
       ); 
+0

インデックスが使用されていません。しかし、私はあなたが最適な指標の意味を不明です。 – user1434177

+0

@ user1434177 。 。最適とは、クエリに最適なインデックスです。テーブルの統計が正しくない可能性があります。 –

+0

ありがとう私はVACUUM ANALYZEを使いました。今は走るのに74msかかる。 – user1434177