2015-06-27 48 views
1

我有一個相當簡單的數據庫模型。我的表的「主」看起來像這樣:性能:使用索引和分區(PostgreSQL)

| id (PK) | device_id (int) | msg_type (int) | rawdata (text) | timestamp (date+time) | 

因此,每個接收到的消息存儲在此表中,包括消息類型,時間戳,發送它和RAWDATA該設備。

此外,對於每個可能的msg_type(總共約30),我有一個單獨的表存儲解析的原始數據。爲表「main_type1」示例:

| id (PK) | main_id (FK) | device_id (int) | attribute_1 | attribute_2 | attribute_n | 

(結構不同爲每個MSG_TYPE和消息不相等地分佈的含義一些表是休一些表是小的)。

請注意,device_id始終包含在rawdata中,因此每個表都包含此列。

現在我的問題:

我曾經有過的查詢,如:

select attribute_1, attribute_2 from main_type1 inner join main on main_type1.main_id = main.id where timestamp > X and timestamp < Y and main.device_id = Z 

在開始的時候一切都已經足夠,也快。但是現在我的數據庫在「main」中有超過400.000.000個條目。查詢現在需要15分鐘。

索引

我試圖使用索引,如:

CREATE INDEX device_id_index ON main (device_id); 

好了,現在我可以更快地從主表retreive數據,但它不加入幫助。我最大的問題在於我只在主表中存儲了時間戳信息。所以我必須一直加入......這是我的數據庫模型的一般故障嗎?我試圖避免兩次存儲時間戳。

分區

將一個解決方案是創建RAWDATA爲每一個新表使用分區DEVICE_ID?然後,我會(當然會自動)創建適當的分區,如:

main_device_id_343223 
main_device_id_4563 
main_device_id_92338 
main_device_id_4142315 

這會給我與速度有關的加入優勢嗎?我還有什麼其他選擇?爲了完整起見:我使用PostgreSQL

+0

分區不是查詢性能特徵,與使用良好的索引策略相比,它通常會使查詢性能變差。 – usr

+1

當你的查詢根本沒有提到設備時,你爲什麼要在設備上建立索引? – usr

+0

@usr:你說得對,我在查詢中添加了缺失的ID。當然,我正在嘗試爲特定設備獲取數據。感謝您指出了這一點! – Anonymous

回答

2

由於您的問題是一個join的執行時間,要做的第一件事就是嘗試通過下列方式創建索引,以加快查詢:

  1. 索引,幫助加盟本身,在這種情況下main_type1外鍵main.id索引(注意,外鍵聲明不會自動創建索引):

    CREATE INDEX main_type_main_id_index ON main_type1(main_id); 
    
  2. 個指標,幫助在限制集由查詢考慮的數據,在這種情況下,對時間戳屬性:

    CREATE INDEX main_timestamp_index ON main(timestamp); 
    

你也可以考慮爲屬性時間戳創建Partial Index的可能性,如果你的查詢只查找值的特定子集。

如果這些索引不能以顯着的方式加快查詢速度,那麼您應該遵循@klin的答案。

+0

這看起來更像是評論而不是答案。如果其答案擴展或添加更多細節,則將其刪除並添加爲問題的評論。 – Ram

+0

感謝評論@Ram,我擴展了查詢,因爲我認爲它可能是問題的解決方案。 – Renzo

+0

感謝您擴大答案。我編輯它來改善它。 – Ram

1

我會建議這樣一個場景:首先,創建Renzo提出的索引。如果這不足以提高性能,請嘗試使用分區。

From the documentation:

分區可以提供幾個好處:查詢性能可以 在某些情況下,顯着改善特別是當大部分 表的頻繁訪問的行是在一個單一的分區或 少數的分區。分區替代了前導索引的索引列,從而減少了索引大小,並使索引的重用部分更適合內存。 (...)

如果使用分區,包含對特定設備的引用的所有查詢(例如在您的問題中)將快得多。 只有適用於許多device_id的查詢(例如包含聚合)可能會變慢。