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)"
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になります)。実際には、出力の順序は通常よりも安定していますが、常にそうであるとは限らないため、出力順序の突然の変化が望ましくない動作を引き起こす場合は、常に順序句を指定する必要があります。