1

feed_entriesRails と postgresql を使用して RSS フィードを読み取るための単純なアプリを作成しましたが、複数のフィードからの投稿についてテーブルにクエリを実行しようとすると、パフォーマンスの問題が発生します。クエリの例は次のようになります。特定のフィード ID のコレクションの最新の 20 個のエントリを取得します。

SELECT * FROM feed_entries WHERE feed_id IN (19, 21, 383, 1867, 3103) ORDER BY published_at DESC LIMIT 20;

このfeed_entriesテーブルには約 400 万行あり、Fugu プランを使用して Heroku Postgres でホストされており、次のようないくつかのインデックスがあります。

"index_feed_entries_on_feed_id_and_published_at" btree (feed_id, published_at)
"index_feed_entries_on_published_at" btree (published_at)

クエリプランナーの結果は次のとおりです。

EXPLAIN ANALYZE SELECT * FROM feed_entries WHERE feed_id IN (19, 21, 383, 1867, 3103) ORDER BY published_at DESC LIMIT 20;

 Limit  (cost=4353.93..4353.94 rows=20 width=1016) (actual time=12172.275..12172.325 rows=20 loops=1)
   ->  Sort  (cost=4353.93..4355.07 rows=2286 width=1016) (actual time=12172.268..12172.284 rows=20 loops=1)
     Sort Key: published_at
     Sort Method: top-N heapsort  Memory: 52kB
     ->  Index Scan using index_feed_entries_on_feed_id_and_published_at on feed_entries  (cost=0.00..4341.76 rows=2286 width=1016) (actual time=8.612..12169.504 rows=630 loops=1)
           Index Cond: (feed_id = ANY ('{19,21,383,1867,3103}'::integer[]))
Total runtime: 12172.520 ms

プランナーは適切なインデックスを使用しているように見えますが、インデックスのスキャンにはまだ 12 秒ほどかかります。これは、400 万行のテーブルには長すぎるように感じます。クエリ プランナーを上記とまったく同じように繰り返すと、2 回目には全体が 2 ミリ秒しかかからないことがわかります。これは単に最初のクエリの結果がキャッシュされているためかもしれませんが、それでも混乱します。クエリを実行する前に実行も試みVACUUM ANALYZEましたが、ほとんど違いはありませんでした。さらに、単一の feed_id についてテーブルにクエリを実行すると、クエリ プランナーは を使用しIndex Scan Backward using index_feed_entries_on_feed_id_and_published_at on feed_entries、合計実行時間は 20 ミリ秒程度と大幅に短縮されます。

この比較的単純な IN クエリのパフォーマンスを最適化するために採用できる他の戦略はありますか?

4

2 に答える 2

1

もう 1 つの試してみるべきことは、次の代替クエリ形式です。

SELECT * 
FROM   feed_entries
JOIN  (unnest('{19,21,383,1867,3103}'::int[]) AS feed_id) sub USING (feed_id)
ORDER  BY published_at DESC
LIMIT  20;

ただし、複数列のインデックスで、列の並べ替え順序は重要です。使用する:

CREATE index_feed_entries_2 ON feed_entries (feed_id, published_at DESC)

CLUSTERこのインデックスに従ってテーブルを作成した場合、これによりさらに少しブーストが得られる可能性がありますが、多くの更新で効果が低下します. 詳細については、この関連する回答の最後の章をお読みください:
ビットマップ ヒープ スキャンのパフォーマンス

もちろん、パフォーマンスの最適化に関する通常のアドバイスもすべて当てはまります。

于 2013-06-27T16:40:11.793 に答える
0

DESC オーダーでインデックスを作成してみてください。例えば。

create index feed_entries_published_at_desc_idx on feed_entries ( published_at desc ) with (fillfactor=100);

(feed_id, published_at desc) で上記と同様の (複合) インデックスを試して、それがどのように機能するかを確認することもできます。

于 2013-06-27T15:50:13.170 に答える