sql >> データベース >  >> RDS >> PostgreSQL

この異常な一致基準を使用して結合を作成するにはどうすればよいですか?

    インデックス

    x.idにインデックスを作成します およびy.id -これらが主キーである場合は、おそらくすでに持っています。
    特にインデックスのみのスキャン 9.2ページ以降:

    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;
    

    SQLフィドル。

    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)は、すべてのローカルテストで直線的にスケーリングします。最新の追加を含めるようにもう一度更新し、フォーマットとパフォーマンスによる順序を改善しました:

    ビッグSQLフィドル パフォーマンスの比較。



    1. T-SQLを使用してSQLServerのリンクサーバーを削除する

    2. JDBCを使用してMicrosoftSQLServer 2008 R2のストアドプロシージャにテーブル値パラメーター(配列のようなパラメーター)を渡す方法は?

    3. 重複した部分文字列の削除

    4. PHPPDOプリペアドステートメントとMySQLを使用してフィールドがnullである行を選択する