に触発された この質問 SET NOCOUNTで異なる見方があるところ==.
SQL ServerにはSET NOCOUNT ONを使用する必要がありますか?そうでない場合は、なぜですか?
それがすること編集6、2011年7月22日
DML後の「影響を受けるxx行」メッセージを抑制します。これは結果セットであり、送信時にはクライアントが処理する必要があります。非常に小さいですが、測定可能です(下記の回答を参照)。
トリガーなどの場合、クライアントは複数の「影響を受けたxx行」を受け取ります。これにより、一部のORM、MS Access、JPAなどでさまざまなエラーが発生します(下記の編集を参照)。
背景:
一般的に受け入れられているベストプラクティス(この質問まで私は思った)は、SQL ServerのトリガとストアドプロシージャでSET NOCOUNT ON
を使用することです。私たちはそれをいたるところで使っていますが、簡単なグーグルでもSQL Server MVPの多くが同意していることを示しています。
MSDNは、これが 。net SQLDataAdapter を破る可能性があると言います。
これは、SQLDataAdapterが「影響を受けるn行」メッセージが一致すると想定しているため、まったく単純なCRUD処理に制限されていることを意味します。だから、私は使用することはできません:
質問にはmarc_s(自分のSQLのことを知っている人)は使ってはいけないと言っています。これは私が思うこととは異なります(そして私も自分自身がSQLでもやや有能だと思います)。
私は何かを見逃している可能性があります(明白なことを指摘してください)が、そこにいる人たちはどう思いますか?
注:最近SQLDataAdapterを使用していないため、このエラーが発生してから何年も経ちます。
コメントや質問の後に編集:
編集:もっと考えて...
複数のクライアントがあります。1つはC#SQLDataAdaptorを使用し、もう1つはJavaのnHibernateを使用します。これらはSET NOCOUNT ON
を使用してさまざまな方法で影響を受ける可能性があります。
ストアドプロシージャをメソッドと見なしている場合は、内部処理の一部が自分の目的に適した方法で機能すると想定するのは不適切な形式(アンチパターン)です。
編集2:a nHibernateの質問を破るきっかけ 、ここでSET NOCOUNT ON
は設定できません
(そしていいえ、それは this の複製ではありません)
編集3:MVPの同僚に感謝する
編集4:2011年5月13日
編集5:14 6月2011
テーブル変数を含むストアドプロシージャのJPAを中断します。 JPA 2.0はSQL Serverのテーブル変数をサポートしますか?
編集6:2011年8月15日
SSMSの[行の編集]データグリッドには、SET NOCOUNT ONが必要です。 GROUP BYを使用してトリガを更新
編集7:2013年3月7日
@RemusRusanuによるより詳細な詳細:
SET NOCOUNT ONは実際にはそれほどパフォーマンスの違いを生み出します
さて、私は今私の研究をしました、これが契約です:
TDSプロトコルでは、SET NOCOUNT ON
は クエリあたり9バイト を節約するだけですが、テキスト "SET NOCOUNT ON"自体はなんと14バイトです。私は123 row(s) affected
が別のネットワークパケットでプレーンテキストでサーバーから返されたと思っていましたが、そうではありません。それは実際には応答に埋め込まれたDONE_IN_PROC
と呼ばれる小さな構造体です。これは独立したネットワークパケットではないので、ラウンドトリップは無駄になりません。
パフォーマンスを気にせずに、ほとんど常にデフォルトのカウント動作に従うことができると思います。ただし、前方スクロールカーソルのように、行数を事前に計算するとパフォーマンスに影響を与える場合があります。その場合、NOCOUNTが必要になるかもしれません。それ以外は、「可能な限りNOCOUNTを使用する」というモットーに従う必要はまったくありません。
これがSET NOCOUNT
設定の無意味についての非常に詳細な分析です: http://daleburnett.com/2014/01/everything-ever-wanted-wanted-know-set-nocount/
NOCOUNTの周りの本当のベンチマークの数字を見つけるには私に多くの掘り下げが必要だったので、私は簡単な要約を共有することにしました。
SET NOCOUNTがONの場合、カウント(Transact-SQLステートメントの影響を受けるローの数を示す)は返されません。 SET NOCOUNTがOFFのときはカウントを返します。 SELECT、INSERT、UPDATE、DELETEステートメントで使用されます。
SET NOCOUNTの設定は、解析時ではなく実行時または実行時に設定されます。
SET NOCOUNT ONを使用すると、ストアドプロシージャ(SP)のパフォーマンスが向上します。
構文:SET NOCOUNT {ON | 0} OFF}
SET NOCOUNT ONの例
SET NOCOUNT OFFの例:
私はある程度DBA対開発者の問題だと思います。
ほとんどの開発者として、絶対に積極的に行う必要がある場合を除き、使用しないでください。使用するとADO.NETコードが破損する可能性があります(Microsoftのドキュメントにあるとおり)。
そして私はDBAだと思います、あなたは反対側にもっといるでしょう - あなたが本当にそれの使用を妨げなければならないのでない限り可能な限りそれを使用してください。
また、開発者がADO.NETのExecuteNonQuery
メソッド呼び出しによって返される "RecordsAffected"を使用する場合、全員がSET NOCOUNT ON
を使用すると問題が生じます。この場合、ExecuteNonQueryは常に0を返すためです。
Peter Brombergの blog post も見て、彼の立場を調べてください。
それで、それは本当に誰が標準を設定することになるかということになります:-)
マーク
別のクライアントがあるかもしれないと言っているのであれば、SET NOCOUNTがONに設定されていなければ、古典的なADOに問題があります。
私が定期的に経験していること:ストアドプロシージャがいくつかのステートメントを実行すると(したがって "xxx rows changed"というメッセージが返されると)、ADOはこれを処理できずエラーを投げます "CommandオブジェクトをソースとするRecordsetオブジェクトのActiveConnectionプロパティを変更することはできません。"
したがって、本当にしない正当な理由がない限り、私は一般的にそれをONに設定することを推奨します。あなたは私が行ってもっと読む必要がある本当に本当に良い理由を見つけたかもしれません。
物事がより複雑になる危険性があるので、私は上で見たものすべてに対してわずかに異なる規則を推奨します。
NOCOUNT ON
をprocの先頭に設定します。ただし、格納されているprocからレコードセットを返す前に、また常にSET NOCOUNT OFF
をもう一度設定します。そのため、「実際に結果セットを返す場合を除いて、通常はnocountをオンにしておいてください」。これがどのような方法でもクライアントコードを破壊する可能性があるということを私は知りません、それはクライアントコードがproc内部について何も知る必要がないことを意味します、そしてそれは特に面倒ではありません。
NHibernateを破ったきっかけについては、私はその経験を直接経験しました。基本的に、NHはUPDATEを実行するとき、影響を受ける行数を予想します。トリガーにSET NOCOUNT ONを追加することで、行数をNHの予想数に戻して問題を解決できます。それで、あなたがNHを使うならば、私は間違いなくトリガーのためにそれをオフにすることを勧めます。
SPでの使用に関しては、それは個人的な好みの問題です。私は常に行カウントをオフにしていましたが、それでもまた、どちらにしても本当の強い議論はありません。
別の言い方をすれば、実際にはSPベースのアーキテクチャーから移行することを検討する必要があります。そうしないと、この質問はありません。
SET NOCOUNT ON;
このコード行は、クエリの実行で影響を受ける行数を返さないためにSQLで使用されています。影響を受ける行数が不要な場合は、これを使用してメモリ使用量を節約し、クエリの実行速度を上げることができます。
「SET NOCOUNT ON」でネットワークパケットもラウンドトリップも保存されないことを確認したい
テスト用のSQLServer 2017を別のホストで使用しました(私はVMを使用しました)create table ttable1 (n int); insert into ttable1 values (1),(2),(3),(4),(5),(6),(7) go
create procedure procNoCount as begin set nocount on update ttable1 set n=10-n end
create procedure procNormal as begin update ttable1 set n=10-n end
次に、ツール 'Wireshark'を使用してポート1433でパケットをトレースしました: 'capture filter'ボタン - > 'port 1433'
exec procNoCount
これは応答パケットです:0000 00 50 56 c0 00 08 00 0c 29 31 3f 75 08 00 45 00 0010 00 42 d0 ce 40 00 40 06 84 0d c0 a8 32 88 c0 a8 0020 32 01 05 99 fe a5 91 49 e5 9c be fb 85 01 50 18 0030 02 b4 e6 0e 00 00 04 01 00 1a 00 35 01 00 79 00 0040 00 00 00 fe 00 00 e0 00 00 00 00 00 00 00 00 00
exec procNormal
これは応答パケットです:0000 00 50 56 c0 00 08 00 0c 29 31 3f 75 08 00 45 00 0010 00 4f d0 ea 40 00 40 06 83 e4 c0 a8 32 88 c0 a8 0020 32 01 05 99 fe a5 91 49 e8 b1 be fb 8a 35 50 18 0030 03 02 e6 1b 00 00 04 01 00 27 00 35 01 00 ff 11 0040 00 c5 00 07 00 00 00 00 00 00 00 79 00 00 00 00 0050 fe 00 00 e0 00 00 00 00 00 00 00 00 00
40行目に、 '影響を受けた行'の数である '07'が表示されています。応答パケットに含まれています。余分なパケットはありません。
ただし、保存できる13バイトの余分なバイトがありますが、おそらく列名を減らすよりも価値がありません(例: 'ManagingDepartment'から 'MD')。
だから私はパフォーマンスのためにそれを使用する理由はありません
しかし他の人が言ったようにそれはADO.NETを壊すことができ、私はpythonを使う問題についてもつまずいた。 MSSQL2008 - Pyodbc - 以前のSQLはクエリではなかった
それでは、おそらくまだ良い習慣です...
NOCOUNTをONに設定します。上記のコードは、DML/DDLコマンドの実行後にSQL Serverエンジンによって生成されたメッセージをフロントウィンドウに表示します。
なぜそれをするのですか? SQLサーバーエンジンはステータスを取得してメッセージを生成するためにいくらかのリソースを取るので、それはSqlサーバーエンジンへの過負荷と考えられます。我々は非カウントメッセージをオンに設定します。
クライアントとSQLの間でSET NOCOUNT ONをテストする方法がわからないので、他のSETコマンド "SET TRANSACTION ISOLATION LEVEL READ UNCIMMITTED"についても同様の動作をテストしました。
接続のコマンドを送信してSQLのデフォルトの動作(READ COMMITTED)を変更し、それが次のコマンド用に変更されました。ストアドプロシージャ内でISOLATIONレベルを変更しても、次のコマンドの接続動作は変わりません。
現在の結論
これは "SET NOCOUNT ON"のような他のSETコマンドに関連していると思います
かなり古い質問ですね。しかし更新のためだけに。
"SET NOCOUNT ON"を使用する最良の方法は、それをあなたのSPの最初のステートメントとして置き、最後のSELECTステートメントの直前で再びOFFに設定することです。
SET NOCOUNT ON
が本当に役立つことができる1つの場所は、ループまたはカーソルでクエリを行っているところです。これにより、大量のネットワークトラフィックが増加する可能性があります。
CREATE PROCEDURE NoCountOn
AS
set nocount on
DECLARE @num INT = 10000
while @num > 0
begin
update MyTable SET SomeColumn=SomeColumn
set @num = @num - 1
end
GO
CREATE PROCEDURE NoCountOff
AS
set nocount off
DECLARE @num INT = 10000
while @num > 0
begin
update MyTable SET SomeColumn=SomeColumn
set @num = @num - 1
end
GO
SSMSでクライアント統計をオンにすると、EXEC NoCountOn
とEXEC NoCountOff
を実行すると、NoCountOffのトラフィックに390KBのトラフィックが追加であることがわかります。
ループやカーソルでクエリを実行するのはおそらく理想的ではありませんが、理想的な世界には住んでいません:)
if(カウント数を設定しない== off)
{その後、影響を受けたレコード数のデータを保持するためパフォーマンスが低下します}それ以外の場合{変更のレコードを追跡しないため、パフォーマンスが向上します}}
時には最も簡単なことでも違いが出ることがあります。すべてのストアドプロシージャに含まれるべきこれらの単純な項目の1つはSET NOCOUNT ON
です。ストアドプロシージャの先頭に置かれるこの1行のコードは、各T-SQLステートメントが実行された後にSQL Serverがクライアントに返すメッセージをオフにします。これは、すべてのSELECT
、INSERT
、UPDATE
、およびDELETE
ステートメントに対して実行されます。クエリウィンドウでT-SQLステートメントを実行するときにこの情報があると便利ですが、ストアドプロシージャが実行されるときにこの情報をクライアントに返す必要はありません。
この余分なオーバーヘッドをネットワークから取り除くことで、データベースとアプリケーションの全体的なパフォーマンスを大幅に向上させることができます。
実行中のT-SQLステートメントの影響を受ける行数を取得する必要がある場合でも、@@ROWCOUNT
オプションを使用できます。 SET NOCOUNT ON
を発行することによって、この関数(@@ROWCOUNT
)はまだ機能し、ステートメントによって影響を受けた行数を識別するためにストアドプロシージャで使用することができます。