6

列を持つテーブルがあり、intそこから読み取るのは MAX() int 値だけだとします。

その列にインデックスを作成すると、Postgres はそのインデックスのリバース スキャンを実行してMAX()値を取得できます。しかし、インデックス内の 1 つの行を除いてすべてが単なるオーバーヘッドであるため、完全なインデックスを作成しなくても同じパフォーマンスを得ることができます。

はい、MAX 値を追跡する単一行テーブルを更新するトリガーを作成しMAX()、メイン テーブルに対して を発行する代わりに、そのテーブルにクエリを実行できます。しかし、Postgres には部分的なインデックスがあることを知っているので、エレガントなものを探しています。この目的のためにそれらを活用する方法が見つからないようです。

更新: この部分インデックスの定義は理想的なものですが、Postgres では部分インデックスの WHERE 句でサブクエリを使用できません。

create index on test(a) where a = (select max(a) from test);

4

2 に答える 2

8

部分インデックスの述語では、集計関数またはサブクエリ式を使用できません。いずれにせよ、インデックス エントリの性質を考えると、これは論理的にはほとんど意味がありません。IMMUTABLE

ただし、整数の範囲があり、最大値が常に より大きいことを保証xできる場合は、このメタ情報を利用できます。

CREATE INDEX text_max_idx ON test (a) WHERE a > x;

WHEREこのインデックスは、インデックスの述語に一致する句を含めた場合にのみ、クエリ プランナーによって使用されます。例えば:

SELECT max(a) FROM test WHERE a > x;

条件は他にもありますが、インデックスを使用するにはこれを含める必要があります。
ただ、「保証」に関しては本気です。述語が false の場合、クエリは何も返しません。

フェイルセーフを構築できます:

SELECT COALESCE( (SELECT max(a) FROM test WHERE a > x)
                 (SELECT max(a) FROM test));

このアプローチは、複数の部分インデックスで一般化できます。この手法に似ていますが、はるかに単純です。

ただし、テーブルへの非常に大きな書き込み負荷を除いて、トリガー アプローチを検討します。

于 2013-07-24T17:59:28.100 に答える
6

インデックス内の他の行は、削除された場合や更新によって現在の最大値が減少した場合でも最大値を正確に保つことができるため、不要ではありません。

そのような操作がない場合 (IOW の最大値のみが増加する場合)、最大値を自分で維持できます。アプリケーション コードまたはトリガーで実行します。

Postgres は、最大値が増加するだけであることを認識できません。削除と更新を行う機能を維持する必要があります。

于 2013-07-24T19:14:00.323 に答える