回答:
答えは、いつものように(大抵の場合)、実行計画にあります。
これらの行の処理を開始して下流に渡す前に、すべての行が到着することを必要とする特定の演算子があります。次に例を示します。
これらは、ブロッキングと呼ばれるか、またはこのためストップアンドゴーオペレーターのいずれかであり、多くのデータを処理してデータを見つける必要があるとオプティマイザーが考える場合にしばしば選択されます。
ストリーミングを開始できる、または見つかった行をすぐに渡すことができる他の演算子があります
クエリがすぐにデータを返し始めてもすぐに終了しない場合は、通常、オプティマイザが起動コストの低い演算子を使用していくつかの行をすばやく見つけて返す計画を選択したことを示しています。
これは、ユーザーまたはオプティマイザーによって行の目標が導入されたために発生する可能性があります。
何らかの理由(SARGabilityの欠如、パラメータスニッフィング、不十分な統計など)で悪い計画が選択された場合にも発生する可能性がありますが、それを見つけるにはさらに掘り下げる必要があります。
詳細については、Rob Farleyのブログをご覧ください。
そして、ポール・ホワイトのシリーズ行の目標にここ、ここ、ここ、とここに。
また、SSMSについて話している場合、行が表示されるのは、意志だけではなく、バッファ全体がいっぱいになると表示されることにも注意してください。
あなたが観察していることを理解すると、これがManagement Studioが行をレンダリングする方法であり、SQL Server が行を返す方法とはほとんど関係ありません。実際、SSMSに大きな結果を返してグリッドにレンダリングしようとすると、SSMSが追いつかず、SQL Serverがアプリがより多くの行を処理するのを待つことになります。この場合、SQL ServerがASYNC_NETWORK_IO
待機を蓄積していることがわかります。
SSMSはグリッドを描画するよりも高速にテキストを描画できるため、Results to Gridの代わりにResults to Textを使用することでいくらか制御できますが、列の数と関連するデータ型によっては読みやすさに影響する可能性があります。どちらも、SSMSがそのペインに結果を実際に書き出すことを決定するときの影響を受けます。これは、出力バッファーがどれだけいっぱいになっているかによって異なります。
あなたが持っている場合は、複数の文を、あなたがメッセージペインに出力結果をレンダリングするために、バッファを強制したい、あなたは文の間に少し印刷トリックを使用することができます。
RAISERROR('', 0, 1) WITH NOWAIT;
ただし、すべての出力が単一のステートメントから来ているときに、SSMSで行をより速くレンダリングしようとする場合、これは役に立ちません。
より直接的に、SSMSでレンダリングする結果の数を制限することで、それを制御できます。グリッドに100万行を返すのにかかる時間について人々が不満を言うのをよく見ます。一体誰もがSSMSグリッドの100万行で何をするのか、私にはわかりません。
のようないくつかのハックがありますOPTION (FAST 100)
。これは、最初の100行(またはouterがない場合は100行)を取得するために最適化されORDER BY
ますが、残りの行とより多くの計画の取得が非常に遅くなります全体的に非効率的であるため、実際に行くべきオプションではありません。
あなたの質問は、SQLServer自体に関するものではありませんが、次のとおりです。
これを制御する方法はありますか?
短い答え:
sqlcmd
代わりに試してくださいssms
sqlcmd
ssms
長い答え:
もちろん!しかし、1つではありません-問題
sqlcmd
でsqlcmd
-modeを使用して、または-modeでクエリを実行します。spid
、セッション設定の完全なリストを取得します。sqlcmd
セッションの設定と比較します。何もクリックしない場合-すべてのセッション設定をプロファイラーからクエリスクリプトにコピーし、sqlcmd
-mode で実行し、徐々に原因を見つけて設定を切り替えます。がんばろう!
sp_BlitzErikの回答に追加するにNOT IN ()
は、サブ選択でa を使用した例を取り上げます。アイテムがネストされたクエリの結果に含まれているかどうかを判断するには、(通常)結果全体を取得する必要があります。
したがって、このようなクエリのパフォーマンスを向上させるために見つけた簡単な方法の1つはLEFT OUTER JOIN
、RIGHT
sideの条件がnull であるように書き換えることです(もちろん、誰でも使用できRIGHT OUTER JOINS
ます)。これにより、結果がすぐに返され始めます。
WHERE t.x IN (<complex SELECT subquery>)
等価LEFT JOIN、をチェックする前に副選択全体を評価する必要がある場合、副問い合わせも評価する必要がLEFT JOIN (<complex SELECT subquery>) AS r ON r.x = t.x .... WHERE r.x IS NULL
あります(そのため、NOT INバージョン)。
NOT EXISTS
がNOT IN
、クエリではOracle が好まれました。しかし、今日それは計画ジェネレーターのエラーと見なされる必要があります