クエリは厳密には同等ではありません
コンテキストを明確にするには:
-
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
。
しかし、それは現在、すべて問題にねじれています。クリーンアップされるまで待機します。