web-dev-qa-db-ja.com

すべての結果セットのユニオンに対してオフセット/制限を実行するために使用されるアルゴリズム

2つの結果セットがあります。

rs1

     id       name
   serial     text
________________
     1        Nick
....................
  1233112     Pete

rs2

     id       name
   serial     text
________________
  123121      Mike
....................
 221233112   Junior

クエリを書く場合:

SELECT *
FROM
(

    SELECT *
    FROM rs1

    UNION ALL

    SELECT *
    FROM rs2

) as rs
OFFSET 100000 LIMIT 10;

クエリの結果はどのように計算されましたか?使用されるアルゴリズムは何ですか?

サーバーはunion全体をロードせずに繰り返し評価し、必要な結果を返すという意味で遅延評価を実行すると思います。

追加として、他のSQLサーバーで使用しているアルゴリズムについて説明していただければ幸いです。

UPD:私はデータベースの内部はかなり新しく、クエリのexectuinプランについてsql-server自体に質問することが可能かどうかわかりません。

クエリプランは次のとおりです。

"Limit  (cost=77.11..77.88 rows=10 width=522)"
"  ->  Append  (cost=0.00..140.18 rows=1818 width=522)"
"        ->  Seq Scan on tbl  (cost=0.00..70.09 rows=909 width=522)"
"        ->  Seq Scan on tbl tbl_1  (cost=0.00..70.09 rows=909 width=522)"

ID順のsaqmeクエリ:

"Limit  (cost=33.16..36.42 rows=10 width=522)"
"  ->  Merge Append  (cost=0.56..593.16 rows=1818 width=522)"
"        Sort Key: tbl.id"
"        ->  Index Scan Backward using pk_tabl on tbl (cost=0.28..285.21 rows=909 width=522)"
"        ->  Index Scan Backward using pk_tbl on tbl tbl_1  (cost=0.28..285.21 rows=909 width=522)"
2
Dmitrii Bundin

OFFSETのような制限句が適用されるタイミングは、クエリ、特に結果の順序付けに依存します。

結果のフィルター処理にも使用されている列(たとえば、WHERE句内)で順序付けされており、インデックスが付けられている場合、制限が早く適用されることがよくあります。クエリプランナーは、検索条件に一致する最初の行のみを見つけようとします。それ以外の場合、通常は制限が他のすべての後に適用されるため、サーバーは結果を一時ストアにスプールしてから、OFFSET/LIMITフィルターをソートして適用します。

UNIONクエリ自体は、クエリプランナーの頭脳に依存するため、計画の出力を調べて知る必要がある場合があります(私はpostgresの専門家ではありません)。残りのクエリの詳細。ただし、作業は行われます(パフォーマンスに影響します)出力は同じですが、制限は完全な結果に適用されます。

この例では、UNIONクエリが実際にrsという名前の派生テーブルを提供しています。制限は間違いなくここの結果全体に適用されるため、SELECT * FROM <some_table> OFFSET 100000 LIMIT 10を実行した場合と機能的には同じです。これらは同じなので、例を単純に書き直すことができます。

SELECT * FROM rs1
UNION ALL
SELECT * FROM rs2
OFFSET 100000 LIMIT 10;

結果は同じになります。

重要な注意点の1つとして、ここではany順序付け句を指定していません。これは、最小限の例を示しているので、すでに知っていることを言っている場合は許してください。ただし、順序付け句がない場合は、出力順序が任意であり、ランダムであり、実行のたびに変わる可能性が高いと想定してください同じクエリ。場合によってはこれで問題ありません(データが必要で、順序は気にしない)が、OFFSET/LIMIT/TOP/... OFFSET 10000 LIMIT 10の後のクエリはOFFSET 10010 LIMIT 10になる可能性が高く、順序付けによって10の異なる行が確実に必要になるため、順序を気にします(理論的には終了できる任意の10ではありません)前回と同じ10になります)。実際には、出力の順序は通常よりも安定していますが、常にそうであるとは限らないため、出力順序の突然の変化が望ましくない動作を引き起こす場合は、常に順序句を指定する必要があります。

2
David Spillett