web-dev-qa-db-ja.com

SET NOCOUNT ON使用方法

に触発された この質問 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処理に制限されていることを意味します。だから、私は使用することはできません:

  • 重複を避けるためにIFが存在する(メッセージに影響を与える行はありません)注:注意して使用してください
  • 存在しない場所(予想される行数より少ない)
  • 些細な更新を除外する(例:実際にはデータが変更されていない)
  • ログ記録などの前にテーブルアクセスを実行します。
  • 複雑さや非正規化を隠す

質問には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日

指定しないとLinq 2 SQLも壊れますか?

編集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は実際にはそれほどパフォーマンスの違いを生み出します

307
gbn

さて、私は今私の研究をしました、これが契約です:

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/

215
Sedat Kapanoglu

NOCOUNTの周りの本当のベンチマークの数字を見つけるには私に多くの掘り下げが必要だったので、私は簡単な要約を共有することにしました。

  • ストアード・プロシージャーがカーソルを使用して結果を返さずに非常に速い操作を多数実行する場合、NOCOUNTをOFFにすると、ONにするまでに約10倍の時間がかかります。 1 これが最悪のシナリオです。
  • ストアドプロシージャが結果を返さずに単一のクイック操作のみを実行する場合、NOCOUNTをONに設定すると、パフォーマンスが約3%向上します。 2 これは通常の挿入または更新手順と一致します。
  • ストアドプロシージャが結果を返す場合(つまり、何かを選択した場合)、パフォーマンスの違いは結果セットのサイズに比例して減少します。
82
  • 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の例

enter image description here

SET NOCOUNT OFFの例:

enter image description here

67
Bhaumik Patel

私はある程度DBA対開発者の問題だと思います。

ほとんどの開発者として、絶対に積極的に行う必要がある場合を除き、使用しないでください。使用するとADO.NETコードが破損する可能性があります(Microsoftのドキュメントにあるとおり)。

そして私はDBAだと思います、あなたは反対側にもっといるでしょう - あなたが本当にそれの使用を妨げなければならないのでない限り可能な限りそれを使用してください。

また、開発者がADO.NETのExecuteNonQueryメソッド呼び出しによって返される "RecordsAffected"を使用する場合、全員がSET NOCOUNT ONを使用すると問題が生じます。この場合、ExecuteNonQueryは常に0を返すためです。

Peter Brombergの blog post も見て、彼の立場を調べてください。

それで、それは本当に誰が標準を設定することになるかということになります:-)

マーク

32
marc_s

別のクライアントがあるかもしれないと言っているのであれば、SET NOCOUNTがONに設定されていなければ、古典的なADOに問題があります。

私が定期的に経験していること:ストアドプロシージャがいくつかのステートメントを実行すると(したがって "xxx rows changed"というメッセージが返されると)、ADOはこれを処理できずエラーを投げます "CommandオブジェクトをソースとするRecordsetオブジェクトのActiveConnectionプロパティを変更することはできません。"

したがって、本当にしない正当な理由がない限り、私は一般的にそれをONに設定することを推奨します。あなたは私が行ってもっと読む必要がある本当に本当に良い理由を見つけたかもしれません。

11
Chris J

物事がより複雑になる危険性があるので、私は上で見たものすべてに対してわずかに異なる規則を推奨します。

  • Procで作業を行う前に、常にNOCOUNT ONをprocの先頭に設定します。ただし、格納されているprocからレコードセットを返す前に、また常にSET NOCOUNT OFFをもう一度設定します。

そのため、「実際に結果セットを返す場合を除いて、通常はnocountをオンにしておいてください」。これがどのような方法でもクライアントコードを破壊する可能性があるということを私は知りません、それはクライアントコードがproc内部について何も知る必要がないことを意味します、そしてそれは特に面倒ではありません。

9
Tao

NHibernateを破ったきっかけについては、私はその経験を直接経験しました。基本的に、NHはUPDATEを実行するとき、影響を受ける行数を予想します。トリガーにSET NOCOUNT ONを追加することで、行数をNHの予想数に戻して問題を解決できます。それで、あなたがNHを使うならば、私は間違いなくトリガーのためにそれをオフにすることを勧めます。

SPでの使用に関しては、それは個人的な好みの問題です。私は常に行カウントをオフにしていましたが、それでもまた、どちらにしても本当の強い議論はありません。

別の言い方をすれば、実際にはSPベースのアーキテクチャーから移行することを検討する必要があります。そうしないと、この質問はありません。

5
zvolkov
SET NOCOUNT ON;

このコード行は、クエリの実行で影響を受ける行数を返さないためにSQLで使用されています。影響を受ける行数が不要な場合は、これを使用してメモリ使用量を節約し、クエリの実行速度を上げることができます。

1
user1509

「SET NOCOUNT ON」でネットワークパケットもラウンドトリップも保存されないことを確認したい

テスト用のSQLServer 2017を別のホストで使用しました(私はVMを使用しました)create table ttable1 (n int); insert into ttable1 values (1),(2),(3),(4),(5),(6),(7) gocreate procedure procNoCount as begin set nocount on update ttable1 set n=10-n endcreate 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はクエリではなかった

それでは、おそらくまだ良い習慣です...

1
phil_w

NOCOUNTをONに設定します。上記のコードは、DML/DDLコマンドの実行後にSQL Serverエンジンによって生成されたメッセージをフロントウィンドウに表示します。

なぜそれをするのですか? SQLサーバーエンジンはステータスを取得してメッセージを生成するためにいくらかのリソースを取るので、それはSqlサーバーエンジンへの過負荷と考えられます。我々は非カウントメッセージをオンに設定します。

1
Subhransu Panda

クライアントとSQLの間でSET NOCOUNT ONをテストする方法がわからないので、他のSETコマンド "SET TRANSACTION ISOLATION LEVEL READ UNCIMMITTED"についても同様の動作をテストしました。

接続のコマンドを送信してSQLのデフォルトの動作(READ COMMITTED)を変更し、それが次のコマンド用に変更されました。ストアドプロシージャ内でISOLATIONレベルを変更しても、次のコマンドの接続動作は変わりません。

現在の結論

  1. ストアドプロシージャ内で設定を変更しても、接続のデフォルト設定は変更されません。
  2. ADOCOnnectionを使用してコマンドを送信して設定を変更すると、デフォルトの動作が変わります。

これは "SET NOCOUNT ON"のような他のSETコマンドに関連していると思います

0
Rabia Mansour

かなり古い質問ですね。しかし更新のためだけに。

"SET NOCOUNT ON"を使用する最良の方法は、それをあなたのSPの最初のステートメントとして置き、最後のSELECTステートメントの直前で再びOFFに設定することです。

0
KRules

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 NoCountOnEXEC NoCountOffを実行すると、NoCountOffのトラフィックに390KBのトラフィックが追加であることがわかります。

client statistics

ループやカーソルでクエリを実行するのはおそらく理想的ではありませんが、理想的な世界には住んでいません:)

0
bcoughlan

if(カウント数を設定しない== off)

{その後、影響を受けたレコード数のデータを保持するためパフォーマンスが低下します}それ以外の場合{変更のレコードを追跡しないため、パフォーマンスが向上します}}

0
Shubham Sharma

時には最も簡単なことでも違いが出ることがあります。すべてのストアドプロシージャに含まれるべきこれらの単純な項目の1つはSET NOCOUNT ONです。ストアドプロシージャの先頭に置かれるこの1行のコードは、各T-SQLステートメントが実行された後にSQL Serverがクライアントに返すメッセージをオフにします。これは、すべてのSELECTINSERTUPDATE、およびDELETEステートメントに対して実行されます。クエリウィンドウでT-SQLステートメントを実行するときにこの情報があると便利ですが、ストアドプロシージャが実行されるときにこの情報をクライアントに返す必要はありません。

この余分なオーバーヘッドをネットワークから取り除くことで、データベースとアプリケーションの全体的なパフォーマンスを大幅に向上させることができます。

実行中のT-SQLステートメントの影響を受ける行数を取得する必要がある場合でも、@@ROWCOUNTオプションを使用できます。 SET NOCOUNT ONを発行することによって、この関数(@@ROWCOUNT)はまだ機能し、ステートメントによって影響を受けた行数を識別するためにストアドプロシージャで使用することができます。

0
Vinayak Savale