連結物理操作:実行の順序を保証しますか?


12

標準SQLでは、aの結果のunion all順序は保証されていません。だから、次のようなもの:

select 'A' as c union all select 'B'

任意の順序で2つの行を返すことができます(ただし、実際に知っているデータベースでは、「A」が「B」よりも前になります)。

SQL Serverでは、これは「連結」物理操作を使用した実行計画になります。

連結操作が入力をスキャンし、使用可能なレコードがある入力をすべて返すと簡単に想像できます。しかし、私はウェブ上で次の文を見つけました(ここ):

クエリプロセッサは、計画に演算子が表示される順序でこの計画を実行します。最初の計画が一番上で、最後の計画が最後です。

質問:これは実際には本当ですか?これは真実であることが保証されていますか?

Microsoftのドキュメントには、入力が最初から最後まで順番にスキャンされるという参照は見つかりませんでした。一方、実行しようとすると、結果は、入力が実際に順番に処理されていることを示唆しています。

エンジンが一度に複数の入力を処理する方法はありますか?私のテスト(定数よりもはるかに複雑な式を使用)は、並列対応の8コアマシン上で実行され、ほとんどのクエリは並列処理を利用しています。

回答:


10

いいえ、動作を保証するマイクロソフトのドキュメントはないため、保証されていません

さらに、Simple Talkの記事が正しいこと、および連結物理演算子が常に計画に示されている順序で入力を処理すること(非常に可能性が高いこと)を想定し、SQL Serverが常に同じを維持する計画を生成することを保証せずにクエリテキストとクエリプランの間の順序は、わずかに改善されます。

ただし、これについてはさらに調査できます。クエリオプティマイザーが連結演算子の入力を並べ替えることができた場合、sys.dm_exec_query_transformation_statsその最適化に対応して、文書化されていないDMVに行が存在するはずです。

SELECT * FROM sys.dm_exec_query_transformation_stats 
    WHERE name LIKE '%CON%' OR name LIKE '%UNIA%'

SQL Server 2012 Enterprise Editionでは、これにより24行が生成されます。定数に関連する変換の誤った一致を無視すると、連結物理演算子に関連する変換が1つありますUNIAtoCON(すべてを連結に結合)。そのため、物理演算子レベルでは、連結演算子が選択されると、派生元の論理和演算子の順に処理されるように見えます。


実際、それはまったく真実ではありません。コストベースの最適化が完了した後、物理連結演算子への入力を並べ替えることができる最適化後の書き換えが存在します。1つの例は、連結が行ゴールの対象である場合に発生します(したがって、最初に安価な入力から読み取ることが重要な場合があります)。詳細については、Paul WhiteによるUNION ALL最適化を参照してください。

その遅い物理書き換えは、SQL Server 2008 R2までは機能していましたが、回帰により、SQL Server 2012以降には適用されなくなりました。修正が発行されたクエリオプティマイザの修正プログラムで復職このSQL Serverの2014年のためのリライト以降(ではない2012年)が有効になっていること(例えば、トレースフラグ4199を)。


しかし、Logical Union All演算子(UNIA)についてはどうでしょうか?UNIAReorderInputs入力を並べ替えることができる変換があります。また、論理的なUnion Allを実装するために使用できる2つの物理演算子UNIAtoCONUNIAtoMERGE(Union All to Merge Union)もあります。

したがって、クエリオプティマイザー aの入力を並べ替えることができるようUNION ALLです。ただし、一般的な変換ではないようです(UNIAReorderInputs簡単にアクセスできるSQL Serverでの使用はゼロです。オプティマイザーを使用する状況はわかりませんが、UNIAReorderInputsプランガイドまたは使用時に確実に使用されますがプランヒントは、上記の行目標の物理的な再配列入力を使用して生成されたプランを強制するために使用されます。

エンジンが一度に複数の入力を処理する方法はありますか?

連結物理演算子は、計画の並行セクション内に存在できます。多少の困難を伴いましたが、次のクエリを使用して並列連結のプランを作成できました。

SELECT userid, regdate  FROM (  --Users table is around 3mil rows
    SELECT  userid, RegDate FROM users WHERE userid > 1000000
    UNION 
    SELECT  userid, RegDate FROM users WHERE userid < 1000000
    UNION all
    SELECT userid, RegDate FROM users WHERE userid < 2000000
    ) d ORDER BY RegDate OPTION (RECOMPILE)

したがって、厳密な意味では、物理連結演算子は常に一貫した方法で入力を処理するように見えます(上から1番目、下から2番目)。ただし、オプティマイザーは、物理演算子を選択する前に入力の順序を切り替えるか、連結ではなくマージ結合を使用できます。


8

Craig Freedmanによると、連結演算子の実行順序は保証されています。

MSDNブログの彼のブログ投稿「クエリプランの表示」から:

演算子に複数の子がある場合、子の順序が重要であることに注意してください。一番上の子が最初の子で、一番下の子が2番目の子です。連結演算子は、この順序で子を処理します。

オンラインブックからShowplan Logical and Physical Operators Reference

連結物理演算子には、2つ以上の入力と1つの出力があります。連結は、最初の入力ストリームから出力ストリームに行をコピーし、追加の入力ストリームごとにこの操作を繰り返します。


その引用は私が探していたものにかなり近い。私は、その順序で実行されることからその順序で返されることへの飛躍を望んでいますが、この場合、ドキュメントが並列処理を排除していることは残念です。
ゴードンリノフ14年

2

コミュニティwikiの回答

反例を作成できない限り、観察された動作がいずれにせよ常に保証されることを証明できるかどうかはわかりません。それがない場合、結果が返される順序を修正する方法は、もちろん、を追加することORDER BYです。

いくつかのシナリオでクエリが異なる順序で処理されることを実証できる場合、「修正」があるかどうか、または修正が必要かどうかはわかりません。

明確な公式文書がないため、これに依存すべきではないことを示唆しています。これはまさにとのトラブルに人々を得たものの一種であるORDER BY観点では、とGROUP BYせずにORDER BYSQL Server 2005ののオプティマイザがリリースされたとき、8年前、。

SQL Serverの新しいバージョンのすべての新機能(今後追加予定)を使用すると、特定の動作を今日保証できると思われても、それが真実であるとは思われません(そうするように文書化されるまで)。

この動作に依存していない場合でも、結果をどうしますか?とにかく、私は部外ことにより、簡単な会話記事呼び出すことはありません公式を。すべての人にとって、これは観察に基づく単なる推測にすぎません。

Microsoftは、「x」が「y」を行うことを保証されていないという公式文書を発行することはありません。これは、ほぼ10年後も、観察された順序に頼ることはできないと人々に納得させるのに苦労している理由の1つですORDER BY。「保証されていない」という文書はありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.