web-dev-qa-db-ja.com

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ミリ秒かかります。

これは、explainからのクエリプランです。

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))

これは、explain analyzeからの応答です。

 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 ms

参考までに、141559行はsum()の一部です。

現在のインデックスは次のとおりです。

:some_id
:some_id, :first_action_at

work_memは、以前は1 MBに設定されていました(RDSのデフォルト)。これを18 MBに変更しました。

編集:work_memをアップして解決するようで、上記の2番目のインデックスを追加しました。速度は約800ミリ秒になりました。

7
easyjo

マッチングインデックス

あなたの質問をもう一度読んだ後、私はあなたがAmazon Redshiftを実行していないことに気づきましたが、Amazon RDSは、引き延ばされていないPostgresを実行しているようです、少なくとも ドキュメントによると

Amazon RDSは、PostgreSQLのいくつかのバージョンを実行するDBインスタンスをサポートしています。現在、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は、beforefirst_action_atの前に来る必要があることに注意してください。 。詳細:
複数列のインデックスとパフォーマンス

EXPLAIN ANALYZEに「インデックスのみのスキャン」が表示されない場合、最後の列はバラストであり、そのままにしておくことをお勧めします。

CREATE INDEX ON pages(some_id, first_action_at);

(あなたの質問の更新によると、あなたが今持っているように。)

どちらの方法でも、(some_id)だけの別のインデックスは、この複数列のインデックスに対してほとんど提供しません。
複合インデックスは最初のフィールドのクエリにも適していますか?

サーバー構成

すべての 遅いクエリと適切なサーバー構成のための通常のアドバイス が適用され、1 MBのwork_mem設定は、数百万行のDBには低すぎます。ただし、work_memは( ドキュメントごと )であるため、この特定の設定はこの特定のクエリにとって重要ではありません。

内部ソート操作およびハッシュテーブルで使用されるメモリ。

ここではどちらも適用されません。

8