インデックス
x.id
にインデックスを作成します およびy.id
-これらが主キーである場合は、おそらくすでに持っています。
特に
CREATE INDEX y_mult_idx ON y (id DESC, val)
しかし、私のテストでは、このインデックスは最初は使用されませんでした。追加する必要がありました(そうでなければ無意味です)val
ORDER BY
へ 並べ替え順序が一致することをクエリプランナーに納得させるため。クエリ3を参照してください 。
インデックスは、この合成設定ではほとんど違いがありません。ただし、列数が多いテーブルの場合は、val
を取得します。 テーブルからのコストはますます高くなり、「カバー」インデックスがより魅力的になります。
クエリ
1)シンプル
SELECT DISTINCT ON (x.id)
x.id, y.val
FROM x
JOIN y ON y.id <= x.id
ORDER BY x.id, y.id DESC;
DISTINCT
を使用した手法の詳細 この関連する回答の中で:
最初のクエリが適切にスケーリングされないのではないかと疑われたため、いくつかのテストを実行しました。小さなテーブルでは高速ですが、大きなテーブルでは良くありません。 Postgresは計画を最適化せず、O(N²)
のコストで(制限された)クロス結合から開始します 。
2)速い
このクエリはまだかなり単純で、優れた拡張性を備えています。
SELECT x.id, y.val
FROM x
JOIN (SELECT *, lead(id, 1, 2147483647) OVER (ORDER BY id) AS next_id FROM y) y
ON x.id >= y.id
AND x.id < y.next_id
ORDER BY 1;
ウィンドウ関数lead()
インストルメンタルです。このオプションを使用して、最後の行のコーナーケースをカバーするデフォルトを提供します:2147483647
可能な最大の整数
です。 。データ型に適応します。
3)非常にシンプルでほぼ同じ速さ
SELECT x.id
,(SELECT val FROM y WHERE id <= x.id ORDER BY id DESC, val LIMIT 1) AS val
FROM x;
通常、相関サブクエリ 遅くなる傾向があります。しかし、これは(カバーする)インデックスから値を選択するだけでよく、それ以外は非常に単純なので競合する可能性があります。
追加のORDER BY
アイテムval
(大胆な強調)無意味に思えます。ただし、これを追加すると、クエリプランナーは複数列のインデックスy_mult_idx
を使用しても問題がないことを確信できます。 ソート順が一致するため、上から。
EXPLAIN
で 出力。
テストケース
活発な議論と複数の更新の後、私はこれまでに投稿されたすべてのクエリを収集し、簡単な概要のためのテストケースを作成しました。私は1000行しか使用しないので、SQLfiddleは遅いクエリでタイムアウトしません。しかし、上位4つ(Erwin 2、Clodoaldo、a_horse、Erwin 3)は、すべてのローカルテストで直線的にスケーリングします。最新の追加を含めるようにもう一度更新し、フォーマットとパフォーマンスによる順序を改善しました: