2017-08-09 47 views
0

我有一個表call_logs,它包含一個ID,DEVICE_ID,時間戳和其他一些領域一起變量。 我目前正試圖編寫一個查詢,返回最後一次調用,如果它正在爲每個設備工作。 當前我的查詢是這樣的:,Postgres的查詢與指數僅緩慢掃描

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

它返回我想要的信息。 但是我的生產服務器現在變得相當龐大,我在表中有大約6,000,000條記錄。

我增加了一個索引的表:

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

但我得到什麼,我認爲是很慢的時間: 這裏是一個解釋分析F中的查詢:

EXPLAIN ANALYSE SELECT DISTINCT ON (device_id) c.device_id, c.timestamp, c.working, c.id 
                FROM call_logs c 
                 ORDER BY c.device_id, c.timestamp desc; 
    QUERY PLAN 
----------------------------------------------------------------------------------------------------------------------------------------------------------------- 
Unique (cost=0.56..363803.37 rows=120 width=25) (actual time=0.069..2171.201 rows=124 loops=1) 
    -> Index Only Scan using cl_device_timestamp on call_logs c (cost=0.56..347982.87 rows=6328197 width=25) (actual time=0.067..1594.953 rows=6331024 loops=1) 
     Heap Fetches: 8051 
Planning time: 0.184 ms 
Execution time: 2171.281 ms 
(5 rows) 

我只有124個唯一的device_id。我不會認爲這將是一個緩慢的過程與索引?任何想法出了什麼問題?或者爲什麼它如此緩慢?

+1

怎麼樣的執行時間,如果你刪除'DISTINCT'?如果你只想要最後一次調用,你不能添加'LIMIT 1'並且不需要'DISTINCT'嗎? –

+0

儘量避免截然不同,請參閱:https://dba.stackexchange.com/questions/93158/how-to-speed-up-select-distinct – Tisp

+0

但限制1只給我1個設備1每個設備需要1個 – user1434177

回答

0

你的指數是4列,沒有之一。根據四列數據分佈之一,您無法估計複合指數的規模和效率。

下一頁 - 事實上,你只有124不同的設備並不意味着更快的索引。相反 - 較不顯着的價值觀將樹分割成更少的部分,因此部分更大。例如,百萬bigint值的bigserial有一百萬個不同的值,確切的id變得非常快。而布爾列索引掃描只有兩個(三個)值,因此需要更長的時間。

最後一個參數 - 兩秒很慢,確實如此。但考慮到你掃描600萬行,比較時間戳,2秒變得完全可以接受我會說。

您可以犧牲OLTP速度並創建一些觸發器,將每個設備等的數據更改的上次時間戳保存到某個外部表中。然後從短外部表中選擇這些預先彙總的值將爲127個設備花費幾微秒。

0

我落得這樣做:

SELECT DISTINCT d.id, c.timestamp, c.id, c.working 
FROM devices d 
INNER JOIN call_logs c on d.id = c.device_id AND c.timestamp = (SELECT max(t.timestamp) FROM call_logs t WHERE t.device_id = d.id) 

,它結束了好多了

Unique (cost=607.92..608.06 rows=11 width=25) (actual time=3.291..3.344 rows=117 loops=1) 
    -> Sort (cost=607.92..607.95 rows=11 width=25) (actual time=3.289..3.310 rows=117 loops=1) 
     Sort Key: d.id, c."timestamp", c.id, c.working 
     Sort Method: quicksort Memory: 34kB 
     -> Nested Loop (cost=1.05..607.73 rows=11 width=25) (actual time=0.057..3.162 rows=117 loops=1) 
       -> Seq Scan on devices d (cost=0.00..4.18 rows=118 width=8) (actual time=0.006..0.029 rows=119 loops=1) 
       -> Index Only Scan using cl_device_timestamp on call_logs c (cost=1.05..5.10 rows=1 width=25) (actual time=0.007..0.007 rows=1 loops=119) 
        Index Cond: ((device_id = d.id) AND ("timestamp" = (SubPlan 2))) 
        Heap Fetches: 110 
        SubPlan 2 
         -> Result (cost=0.48..0.49 rows=1 width=8) (actual time=0.018..0.018 rows=1 loops=119) 
          InitPlan 1 (returns $1) 
           -> Limit (cost=0.43..0.48 rows=1 width=8) (actual time=0.017..0.017 rows=1 loops=119) 
            -> Index Only Scan Backward using test1 on call_logs t (cost=0.43..2674.01 rows=52483 width=8) (actual time=0.017..0.017 rows=1 loops=119) 
              Index Cond: ((device_id = d.id) AND ("timestamp" IS NOT NULL)) 
              Heap Fetches: 110 
Planning time: 0.645 ms 
Execution time: 3.461 ms 
(18 rows)