Postgresql

RDS 上非常慢的簡單 PostgreSQL 查詢

  • July 7, 2014

在中型 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是(根據文件):

內部排序操作和雜湊表使用的記憶體。

在這裡都不適用。

引用自:https://dba.stackexchange.com/questions/69835