RDS 上非常慢的簡單 PostgreSQL 查詢
在中型 RDS 盒(db.m3.medium,3.7gb ram)上,我的查詢似乎很慢。
這是一個包含 4,152,928 行的表。
select sum(some_field) c from pages where pages.some_id=123 and pages.first_action_at > '2014-01-01 00:00:00 +1000'
總執行時間:45031 毫秒。
在本地,我有大約 110 萬行,相同的查詢大約需要 450 毫秒。
這是查詢計劃,來自解釋:
Aggregate (cost=475640.59..475640.60 rows=1 width=4) -> Seq Scan on pages (cost=0.00..475266.07 rows=149809 width=4) Filter: ((first_action_at > '2014-01-01 00:00:00'::timestamp without time zone) AND (some_id = 447))
以下是解釋分析的回复:
Aggregate (cost=475641.74..475641.76 rows=1 width=4) (actual time=42419.717..42419.718 rows=1 loops=1) -> Seq Scan on pages (cost=0.00..475267.22 rows=149810 width=4) (actual time=0.013..42265.908 rows=141559 loops=1) Filter: ((first_action_at > '2014-01-01 00:00:00'::timestamp without time zone) AND (some_id = 447)) Rows Removed by Filter: 4011369
總執行時間:42419.772 毫秒
作為參考,141559 行是 sum() 的一部分。
我目前的索引是:
:some_id :some_id, :first_action_at
work_mem
之前設置為 1 mb(RDS 預設值)。我剛剛將其更改為 18 MB。編輯:似乎可以通過增加
work_mem
和添加上面的第二個索引來解決,速度現在約為 800 毫秒。
匹配指數
重新閱讀您的問題後,我意識到您執行的不是 Amazon Redshift,而是 Amazon RDS,它似乎正在執行未受污染的 Postgres,至少根據文件:
Amazon RDS 支持執行多個 PostgreSQL 版本的數據庫實例。目前我們支持 PostgreSQL 版本 9.3.1、9.3.2 和 9.3.3。
這意味著您可以使用僅索引掃描。如果您滿足一些先決條件(基本上如果
vacuum
可以跟上寫操作)並且如果some_field
沒有更新到經常且相當小(這似乎是數字列的情況),那麼完美的索引將包含some_field
在最後一個位置(如@zerkms首先提到):CREATE INDEX ON pages(some_id, first_action_at, some_field);
請注意,
some_id
應該在之前first_action_at
,因為首先具有相等性檢查的列和稍後具有範圍的列通常更有效。詳細資訊:如果您在 中沒有看到“僅索引掃描”
EXPLAIN ANALYZE
,則最後一列只是鎮流器,最好不要使用:CREATE INDEX ON pages(some_id, first_action_at);
(就像你現在一樣,根據你的問題更新。)
無論哪種方式,另一個索引
(some_id)
只提供很少的多列索引:伺服器配置
所有關於慢速查詢和正確伺服器配置的常見建議都適用,
work_mem
對於具有數百萬行的數據庫來說,1 MB 的設置太低了。但是這個特定的設置對於這個特定的查詢不應該是至關重要的,因為work_mem
是(根據文件):內部排序操作和雜湊表使用的記憶體。
在這裡都不適用。