2015-10-02 77 views
0

我有以下Postgres查詢,查詢需要10到50秒執行。任何方式來加快這個SQL查詢?

SELECT m.match_id FROM match m 
WHERE m.match_id NOT IN(SELECT ml.match_id FROM message_log ml) 
AND m.account_id = ? 

我已經match_id創建的索引和account_id

CREATE INDEX match_match_id_account_id_idx ON match USING btree 
    (match_id COLLATE pg_catalog."default", 
    account_id COLLATE pg_catalog."default"); 

但還是查詢需要較長的時間。我能做些什麼來加速並提高效率?當我執行幾個這樣的查詢時,我的服務器負載將降至25。

+0

請考慮我添加的[postgresql-performance]標記的tag-info指令。 –

回答

3

NOT IN (SELECT ...)可能會相當昂貴,因爲它必須分開處理NULL。當涉及NULL值時,它也可能很棘手。通常LEFT JOIN/IS NULL(或其他相關技術之一)快:

適用於您的查詢:

SELECT m.match_id 
FROM match m 
LEFT JOIN message_log ml USING (match_id) 
WHERE ml.match_id IS NULL 
AND m.account_id = ?; 

最好的指標是:

CREATE INDEX match_match_id_account_id_idx ON match (account_id, match_id); 

或者只是o n (account_id),假設match_id在兩個表中都是PK。您也已經有message_log(match_id)所需的索引。否則也創建它。

另外COLLATE pg_catalog."default"在索引定義表明,您的ID列是character types,其通常低效。通常最好是integer types

我從你迄今爲止所展示的小小人物中汲取教訓:可能存在更多問題。

+0

爲了解決問題的最佳答案而投票贊成。 – MAK

+0

你的索引和OPING使用'USING btree'有什麼區別?或者什麼使得選擇? –

+0

@Juan:Btree是默認的,'USING btree'只是噪音,沒有區別。正如'COLLATE pg_catalog。「default字符類型一樣。區別在於列的順序。條件是'account_id',所以它應該是第一個:http://dba.stackexchange.com/a/27493/3684 –