クエリは厳密には同等ではありません
コンテキストを明確にするには:
-
max(id)NULLを除外します 値。ただし、ORDER BY ... LIMIT 1しません。 -
NULL値は、最後に昇順で並べ替えられ、最初に降順で並べ替えられます。したがって、Index Scan Backward最大値が見つからない可能性があります(max()によると )最初ですが、任意の数のNULL値。
正式な同等物:
SELECT max(id) FROM testview;
ではありません:
SELECT id FROM testview ORDER BY id DESC LIMIT 1;
しかし:
SELECT id FROM testview ORDER BY id DESC NULLS LAST LIMIT 1;
後者のクエリは、高速クエリプランを取得しません。ただし、ソート順が一致するインデックスを使用する場合:(id DESC NULLS LAST) 。
これは、集計関数min()では異なります。 およびmax() 。テーブルtest1をターゲットにすると、迅速な計画が立てられます。 (id)のプレーンPKインデックスを直接使用する 。ただし、ビューに基づいている場合(または、基になる結合クエリに直接基づいている場合-ビューはブロッカーではありません)ではありません。 NULL値を適切な場所に並べ替えるインデックスは、ほとんど効果がありません。
私たち id このクエリでは、NULLにすることはできません。 。列はNOT NULLで定義されています 。そして、ビューの結合は事実上INNER JOIN NULLを導入することはできません idの値 。
私たち test.idのインデックスも知っています NULL値を含めることはできません。
ただし、PostgresクエリプランナーはAIではありません。 (そうしようともしません。すぐに手に負えなくなる可能性があります。)2つの欠点があります。 :
-
min()およびmax()インデックスの並べ替え順序に関係なく、テーブルをターゲットにする場合にのみ高速プランを取得します。インデックス条件が追加されます:Index Cond: (id IS NOT NULL) -
ORDER BY ... LIMIT 1完全に一致するインデックスの並べ替え順序でのみ高速プランを取得します。
それが(簡単に)改善されるかどうかはわかりません。
db <> fiddle こちら -上記のすべてを示す
インデックス
このインデックスはまったく役に立ちません:
CREATE INDEX ON "test" ("id");
test.idのPK は列に一意のインデックスを付けて実装されており、追加のインデックスが行う可能性のあるすべてのことをすでにカバーしています。
質問が解決するのを待って、もっとあるかもしれません。
歪んだテストケース
テストケースは実際のユースケースから離れすぎているため、意味がありません。
テストセットアップでは、各テーブルに10万行があり、joincolのすべての値が保証されるわけではありません。 反対側に一致があり、両方の列をNULLにすることができます
実際のケースでは、table1に1,000万行あります およびtable2の<100行 、table1.joincolのすべての値 table2.joincolに一致するものがあります 、両方ともNOT NULLで定義されています 、およびtable2.joincol ユニークです。古典的な1対多の関係。 UNIQUEが必要です table2.joincolの制約 およびFK制約t1.joincol --> t2.joincol 。
しかし、それは現在、すべて問題にねじれています。クリーンアップされるまで待機します。