2016-06-11 97 views
0

我目前正在研究數據跟蹤系統。該系統是一個多進程應用程序寫在Python和以下面的方式工作:用於系統任務跟蹤的高效DB解決方案

  1. 每S秒它選擇來自 數據庫(目前的Postgres)N個最適當的任務,並發現數據爲它
  2. 如果有沒有任務,它創建N個新任務並返回到(1)。

問題在於 - 目前我有約。 80GB數據和36M任務以及對任務表的查詢開始工作得越來越慢(它是人口最多,使用最頻繁的表)。

性能的主要瓶頸 是任務追蹤查詢:

LOCK TABLE task IN ACCESS EXCLUSIVE MODE; 
SELECT * FROM task WHERE line = 1 AND action = ANY(ARRAY['Find', 'Get']) AND (stat IN ('', 'CR1') OR stat = 'ERROR' AND (actiondate <= NOW() OR actiondate IS NULL)) ORDER BY taskid, actiondate, action DESC, idtype, date ASC LIMIT 36; 

            Table "public.task" 
    Column |   Type    |     Modifiers 
------------+-----------------------------+------------------------------------------------- 
number  | character varying(16)  | not null 
date  | timestamp without time zone | default now() 
stat  | character varying(16)  | not null default ''::character varying 
idtype  | character varying(16)  | not null default 'container'::character varying 
uri  | character varying(1024)  | 
action  | character varying(16)  | not null default 'Find'::character varying 
reason  | character varying(4096)  | not null default ''::character varying 
rev  | integer      | not null default 0 
actiondate | timestamp without time zone | 
modifydate | timestamp without time zone | 
line  | integer      | 
datasource | character varying(512)  | 
taskid  | character varying(32)  | 
found  | integer      | not null default 0 
Indexes: 
    "task_pkey" PRIMARY KEY, btree (idtype, number) 
    "action_index" btree (action) 
    "actiondate_index" btree (actiondate) 
    "date_index" btree (date) 
    "line_index" btree (line) 
    "modifydate_index" btree (modifydate) 
    "stat_index" btree (stat) 
    "taskid_index" btree (taskid) 

           QUERY PLAN       
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
Limit (cost=312638.87..312638.96 rows=36 width=668) (actual time=1838.193..1838.197 rows=36 loops=1) 
    -> Sort (cost=312638.87..313149.54 rows=204267 width=668) (actual time=1838.192..1838.194 rows=36 loops=1) 
     Sort Key: taskid, actiondate, action, idtype, date 
     Sort Method: top-N heapsort Memory: 43kB 
     -> Bitmap Heap Scan on task (cost=107497.61..306337.31 rows=204267 width=668) (actual time=1013.491..1343.751 rows=914586 loops=1) 
       Recheck Cond: ((((stat)::text = ANY ('{"",CR1}'::text[])) OR ((stat)::text = 'ERROR'::text)) AND (line = 1)) 
       Filter: (((action)::text = ANY ('{Find,Get}'::text[])) AND (((stat)::text = ANY ('{"",CR1}'::text[])) OR (((stat)::text = 'ERROR'::text) AND ((actiondate <= now()) OR (actiondate IS NULL))))) 
       Rows Removed by Filter: 133 
       Heap Blocks: exact=76064 
       -> BitmapAnd (cost=107497.61..107497.61 rows=237348 width=0) (actual time=999.457..999.457 rows=0 loops=1) 
        -> BitmapOr (cost=9949.15..9949.15 rows=964044 width=0) (actual time=121.936..121.936 rows=0 loops=1) 
          -> Bitmap Index Scan on stat_index (cost=0.00..9449.46 rows=925379 width=0) (actual time=117.791..117.791 rows=920900 loops=1) 
           Index Cond: ((stat)::text = ANY ('{"",CR1}'::text[])) 
          -> Bitmap Index Scan on stat_index (cost=0.00..397.55 rows=38665 width=0) (actual time=4.144..4.144 rows=30262 loops=1) 
           Index Cond: ((stat)::text = 'ERROR'::text) 
        -> Bitmap Index Scan on line_index (cost=0.00..97497.14 rows=9519277 width=0) (actual time=853.033..853.033 rows=9605462 loops=1) 
          Index Cond: (line = 1) 
Planning time: 0.284 ms 
Execution time: 1838.882 ms 
(19 rows) 

當然,所有涉及的領域進行索引。我目前想在兩個方向:

  1. 如何優化查詢,並將它實際上給我一個性能改進的角度或不(目前大約需要10秒每次查詢是在動態任務跟蹤不可接受的。 )
  2. 在哪裏以及如何更有效地存儲任務數據 - 可能是我應該使用另一個DB用於這種目的 - Cassandra,VoltDB或另一個大數據存儲?

我認爲應該以某種方式預先設定數據以儘可能快地獲得實際任務。

另請注意,我目前的80G音量極有可能是此類任務的最低音量而非最高音量。

在此先感謝!

+1

1)你是否真的需要所有這些巨大的varchar字段,不能將它們移動到單獨的表中? 2)尤其是主鍵和低基數{status,type,action}字段可以壓縮爲整數類型。 3)對於像這樣的典型*查詢,可以使用部分(*複合*)索引。 4)表格的含義不明確,它似乎結合了{status,action,logging}種事實。 – wildplasser

回答

0

我不太瞭解你的用例,但它並不像我的索引工作得很好。看起來查詢主要依賴於stat索引。我認爲你需要研究一個像(action,line,stat)這樣的複合索引。

另一種選擇是在多個表中分割數據,並將其分割爲低基數的某個鍵。我不使用postgres,但我不認爲看另一個數據庫解決方案會更好地工作,除非你確切知道你正在優化什麼。

+0

你能解釋一下你最後一句話嗎? – Severogor

+0

您提到的其他數據庫每個都擅長某些事情,在其他數據庫上很糟糕。就我個人而言,我認爲postgres是最容易學會如何優化的,所以我會堅持下去,除非你有一個非常有說服力的理由來切換。 (一個stackoverflow答案不會給你足夠的信息,知道你應該除非你已經知道該問什麼)。 –