1

大きなレポート テーブルがあります。ビットマップ ヒープ スキャン ステップに 5 秒以上かかります。

私にできることはありますか?テーブルに列を追加しましたが、それが使用するインデックスを再作成することは役に立ちますか?

データを結合して合計するので、500K レコードをクライアントに返しません。
私はpostgres 9.1を使用しています。
ここで説明します:

 Bitmap Heap Scan on foo_table  (cost=24747.45..1339408.81 rows=473986 width=116) (actual time=422.210..5918.037 rows=495747 loops=1)
   Recheck Cond: ((foo_id = 72) AND (date >= '2013-04-04 00:00:00'::timestamp without time zone) AND (date <= '2013-05-05 00:00:00'::timestamp without time zone))
   Filter: ((foo)::text = 'foooooo'::text)
   ->  Bitmap Index Scan on foo_table_idx  (cost=0.00..24628.96 rows=573023 width=0) (actual time=341.269..341.269 rows=723918 loops=1)

クエリ:

explain analyze
SELECT CAST(date as date) AS date, foo_id, ....
from foo_table
where foo_id = 72
and date >= '2013-04-04'
and date <= '2013-05-05'
and foo = 'foooooo'

Index def:
Index "public.foo_table_idx"
   Column    |            Type
-------------+-----------------------------
 foo_id      | bigint
 date        | timestamp without time zone

 btree, for table "public.external_channel_report"

テーブル: 4 つの異なる値を持つフィールドです
foo。現在、10,000 個の個別の値があります。text
foo_idbigint

4

2 に答える 2

3

コメントへの回答

インデックスと同じ順序で where 列が必要ですか?

WHERE句内の式の順序はまったく関係ありません。SQL は手続き型言語ではありません。

間違いを修正する

タイムスタンプ列には、いくつかの理由から「日付」という名前を付けないでください。明らかに、それはtimestampではなくdateです。しかし、もっと重要なdateことは、これはすべての SQL 標準で予約語であり、Postgres では型と関数の名前であり、識別子として使用すべきではないということです。

質問には、完全なテーブル定義や既存のインデックスに関する決定的な情報など、適切な情報を提供する必要があります。マニュアルのインデックスに関する章を読むことから始めることをお勧めします。

タイムスタンプのWHERE条件は、おそらく正しくありません。

and date >= '2013-04-04'
and date <= '2013-05-05'

タイムスタンプ列の上部境界線は、おそらく除外する必要があります:

and date >= '2013-04-04'
and date <  '2013-05-05'

索引

@Quassnoi が提供する複数列インデックスを使用すると、インデックスの 1 つの連続したデータ ブロックからすべての条件を満たす行を読み取ることができるため、クエリが大幅に高速になります。現在のように、行が無駄に読み取られる (そして後で失格になる) ことはありません。
ただし、500k 行にはまだ時間がかかります。通常、可視性を確認し、テーブルから追加の列をフェッチする必要があります。Postgres 9.2 以降では、インデックスのみのスキャン がオプションになる場合があります。

列の順序はこの方法が最適です。これは、大まかな規則として、最初に等値の列、次に範囲の列であるためです。dba.SE に関するこの関連する回答の詳細とリンク。

CLUSTER/ pg_repack

このインデックスに従ってテーブルを合理化することで、さらに高速化できます。これにより、テーブルから最小限のブロックを読み取る必要があります-それに対して他の要件がない場合!

さらに速くしたい場合は、テーブル内の行の物理的な順序を合理化できます。テーブルを数秒間 (たとえば営業時間外に) 排他的にロックしてテーブルを書き換え、インデックスに従って行を並べ替える余裕がある場合:

ALTER TABLE foo_table CLUSTER ON idx_myindex_idx;

同時使用が問題になる場合は、pg_repack排他ロックなしで同じことができる を検討してください。

効果: テーブルから読み取る必要があるブロックが少なくなり、すべてが事前にソートされます。テーブルに書き込みがある場合、時間の経過とともに悪化する 1 回限りの効果です。そのため、時々再実行します。

dba.SE のこの関連する回答から最後の章をコピーして適応させました。

于 2013-05-05T23:47:43.943 に答える