3

次のように簡単に構成されたテーブルがあります。

tn( id integer NOT NULL primary key DEFAULT nextval('tn_sequence'),
                 create_dt TIMESTAMP NOT NULL DEFAULT NOW(),
                             ...............
                 deleted boolean );

create_dt行がデータベースに挿入されたときのタイムスタンプです。

deleted行が有用であるか、もはや役に立たないことを示します。

そして、次のクエリがあります。

select * from tn where create_dt > ( NOW() - interval '150 seconds ) and deleted = FALSE;
select * from tn where create_dt < ( NOW() - interval '150 seconds ) and deleted = FALSE;

私の質問は、行数が増えるとこれらのクエリがどのように遅くなるかです。たとえば、行数が 10K、20K、または 100K を超える場合、速度に大きな影響を与えるでしょうか? これらのクエリを最適化する方法はありますか? 5 秒ごとに、150 秒より古い行の「削除済み」列を「TRUE」に変更することに注意してください。

4

1 に答える 1

4

テーブルの増加がパフォーマンスに与える影響は、選択したクエリプラン、使用可能なインデックス、クエリの選択性、およびその他の多くの要因によって異なります。EXPLAIN ANALYZEクエリで役立つ場合があります。要するに、クエリが数行しか選択せず、単純なbツリーインデックスを使用できる場合、通常はトンの速度が低下することはなく、インデックスが大きくなるにつれて少しだけ遅くなります。一方、複雑なインデックス付けされていない条件を使用したり、大量の行を返したりするクエリは、実際に非常に悪いパフォーマンスを示す可能性があります。

あなたの問題は、PostgreSQLで古くなった後はクエリされない行をどのように処理する必要があるかという質問を反映しているようです。

そこで与えられたアドバイスが適用されるべきです:

たとえば、次のようになります。

CREATE INDEX create_dt_when_not_deleted_idx 
ON tn (create_dt)
WHERE (NOT deleted);

これには、インデックスに(nullではないとdeleted = 'f'仮定して)含まれる行のみが含まれます。deletedこれは、テーブルから完全に削除することと同じではありません。

  • フルテーブルシーケンシャルスキャンでは何も変わりませんdeleted='t'。行をスキャンする必要があります。と
  • deleted = 't'特定のヒープページにはdeleted = 't'と行が混​​在している可能性が高いため、行が存在しない場合よりも多くのI/Oがありdeleted = 'f'ます。

CLUSTERを含むインデックスを使用することで、後者の影響を減らすことができますdeleted。繰り返しますが、これはシーケンシャルスキャンには影響しません。シーケンシャルスキャンを支援するには、テーブルをに分割する必要がありますdeleted

Pg 9.2のインデックスのみのスキャンでは、部分インデックスを使用する必要があります(テストは行っていないと思います)。deleted = 'f'インデックスのみのスキャンが可能な場合、部分インデックスは、行のみを含むテーブルのインデックスと同じ速度である必要があります。

テーブルとインデックスの肥大化を制御する必要があることに注意してください。autovaccumが非常に頻繁に実行されるようにし、手動で管理される空き領域マップなどを必要とせず、最新の最適な動作のautovacuumを備えた現在のバージョンのPostgreSQLを使用します。9.0以上、できれば9.1または9.2をお勧めします。積極的に実行するように自動真空を調整します。

パフォーマンスを調整およびテストするときはEXPLAIN ANALYZE、推測するだけでなく、でクエリをテストします。

于 2012-10-07T09:49:36.573 に答える