2012-11-24 56 views
3

的LIMIT這是我的表架構優化SELECT查詢使用ORDER BY,OFFSET和PostgreSQL

Column  |   Type   |      Modifiers      
-------------+------------------------+------------------------------------------------------ 
id   | integer    | not null default nextval('message_id_seq'::regclass) 
date_created | bigint     | 
content  | text     | 
user_name | character varying(128) | 
user_id  | character varying(128) | 
user_type | character varying(8) | 
user_ip  | character varying(128) | 
user_avatar | character varying(128) | 
chatbox_id | integer    | not null 
Indexes: 
    "message_pkey" PRIMARY KEY, btree (id) 
    "idx_message_chatbox_id" btree (chatbox_id) 
    "indx_date_created" btree (date_created) 
Foreign-key constraints: 
    "message_chatbox_id_fkey" FOREIGN KEY (chatbox_id) REFERENCES chatboxes(id) ON UPDATE CASCADE ON DELETE CASCADE 

這是查詢

SELECT * 
FROM message 
WHERE chatbox_id=$1 
ORDER BY date_created 
OFFSET 0 
LIMIT 20; 

($ 1將被由實際ID代替)

它運行得非常好,但是當它達到3.7百萬記錄時,所有的SELECT查詢開始消耗大量的CPU和RAM,然後整個系統停機。我必須臨時備份所有當前消息並截斷該表。我不知道發生了什麼,因爲當我有大約2百萬條記錄時,一切正常

我使用Postresql Server 9.1.5和默認選項。


更新解釋所輸出ANALYZE

Limit (cost=0.00..6.50 rows=20 width=99) (actual time=0.107..0.295 rows=20 loops=1) 
-> Index Scan Backward using indx_date_created on message (cost=0.00..3458.77 rows=10646 width=99) (actual time=0.105..0.287 rows=20 loops=1) 
Filter: (chatbox_id = 25065) 
Total runtime: 0.376 ms 
(4 rows) 

更新服務器規範

Intel Xeon 5620 8x2.40GHz+HT 
12GB DDR3 1333 ECC 
SSD Intel X25-E Extreme 64GB 

最終溶液

最後,我可以去以上3級萬元以下的消息,我必須優化PostgreSQL的配置wildplasser建議,也使一個新的索引建議回曆

+0

你可以添加查詢的'EXPLAIN ANALYZE'嗎? –

+2

'我使用Postresql Server 9.1.5和默認選項.'您可以通過將estimated_cache_size設置爲可用RAM的3/4,並將work_mem設置爲〜10M開始。並且*可能*將random_page_cost設置爲1.5。並在所有相關的表格上運行'VACUUM ANALYZE'。 – wildplasser

+0

你最近在桌子上運行過'ANALYZE'嗎? –

回答

8

你可以嘗試給PostgreSQL的該查詢的一個更好的指標。我建議是這樣的:

create index invent_suitable_name on message(chatbox_id, date_created); 

create index invent_suitable_name on message(chatbox_id, date_created desc); 
+1

您不需要爲postgres的索引字段指定'desc'。 Postgres可以在兩個方向上掃描索引。 –

+1

@IgorRomanchenko儘管如此,創建按正確方向排序的索引將使索引掃描速度更快。後向索引掃描速度相當慢。 –

+0

我發表了我的表架構,我已經有chatbox_id和date_created的索引 –

3

嘗試添加一個索引chatbox_id, date_created。對於這個特定的查詢,它會給你最大的性能。

對於這種情況,當postgres「開始消耗大量的CPU和RAM」時,試着獲得更多細節。這可能是一個錯誤(使用默認配置postgres通常不會消耗太多RAM)。

UPD我對於表現不好的原因猜測:

在某個時間點的表變得大了全面掃描,收集準確的統計數據。 Postgresql的另一個ANALYZE得到了糟糕的統計表。因此 - 得到的不好的計劃包括:

  1. 索引掃描在chatbox_id;
  2. 訂購返回的記錄得到由於默認CONFIGS和大量記錄的前20名。

,在返回步驟1中,Postgres的被迫做磁盤整理的文件。結果 - 糟糕的表現。

UPD2 EXPALIN ANALYZE顯示0.376 ms時間和一個很好的計劃。你能否提供一個表現不佳的案例的細節?

+0

我更新了我的服務器規範,我認爲它足以處理3百萬條記錄,不是嗎? –

+0

@laoshanlung使用默認配置postgresql將使用10%的服務器功耗。 +錯誤的查詢計劃會減慢任何服務器的速度。 –