Ustaw NOCOUNT przy użyciu

Zainspirowany tym pytaniem gdzie istnieją różne poglądy na SET NOCOUNT...

Czy powinniśmy używać SET NOCOUNT ON dla SQL Server? Jeśli nie, to dlaczego?

Co robi Edit 6, dnia 22 lip 2011

Tłumi komunikat "XX rows affected" po dowolnym DML. Jest to resultset i po wysłaniu klient musi go przetworzyć. Jest mały, ale mierzalny (zobacz Odpowiedzi poniżej)

Dla wyzwalaczy itp., Klient otrzyma wiele wierszy " XX w przypadku niektórych systemów ORMs, MS Access, JPA itp. (patrz edycje poniżej)

Background:

Ogólnie przyjętą najlepszą praktyką (myślałem, że do tego pytania) jest użycie SET NOCOUNT ON w wyzwalaczach i procedurach składowanych w SQL Server. Używamy go wszędzie i szybkie google pokazuje mnóstwo MVPs SQL Server zgadzają się zbyt.

MSDN mówi, że może to złamać . NET SQLDataAdapter.

To dla mnie oznacza, że SqlDataAdapter jest ograniczony aby całkowicie po prostu przetwarzać CRUD, ponieważ oczekuje, że komunikat "n wierszy dotkniętych" będzie zgodny. Więc nie mogę używać:

  • jeśli istnieje, aby uniknąć duplikatów (wiadomość nie dotyczy wierszy) Uwaga: używaj ostrożnie
  • gdzie nie istnieje (mniej wierszy niż oczekiwano
  • Filtruj trywialne aktualizacje (np. brak faktycznie zmian danych)
  • wykonaj dowolny dostęp do tabeli przed (np. rejestrowanie)
  • Ukryj złożoność lub denormlizację
  • etc

W pytaniu marc_s (kto zna się na SQL-ach) mówi, żeby go nie używać. To różni się od tego, co myślę (i uważam się za nieco kompetentnego w SQL też).

Możliwe, że coś mi umyka( nie krępuj się wskazać oczywistego), ale co wy na to?

Uwaga: minęły lata odkąd zobaczyłem ten błąd, ponieważ nie używam SQLDataAdapter obecnie.

Zmiany po komentarzach i pytaniach:

Edit: więcej myśli...

Mamy wielu klientów: jednego może używać C # SQLDataAdaptor, inny może używać NHibernate z Javy. Można na nie wpływać w różny sposób za pomocą SET NOCOUNT ON.

Jeśli traktujesz przechowywane proc jako metody, to złą formą (anty-pattern) jest zakładanie, że jakieś wewnętrzne przetwarzanie działa w określony sposób dla Twoich własnych celów.

Edit 2: a trigger breaking nHibernate question , gdzie SET NOCOUNT ON nie można ustawić

(i nie, to nie jest duplikat tego )

Edit 3: jeszcze więcej informacji, dzięki mojemu MVP kolega

Edit 4: 13 May 2011

Łamie też Linq 2 SQL gdy nie jest określony?

Edit 5: 14 Jun 2011

Łamie JPA, przechowywane proc ze zmiennymi tabeli: czy JPA 2.0 obsługuje zmienne tabeli SQL Server?

Edit 6: 15 Aug 2011

Siatka danych SSMS "Edytuj wiersze" wymaga ustawienia NOCOUNT ON: Update trigger with GROUP BY

Edit 7: 07 Mar 2013

Więcej Szczegółów od @ RemusRusanu:
czy ustawienie NOCOUNT na naprawdę sprawia, że tak duża różnica w wydajności

Author: gbn, 2009-09-27

12 answers

Ok teraz zrobiłem swoje badania, oto umowa:

W protokole TDS, SET NOCOUNT ONzapisuje tylko 9 bajtów na zapytanie, podczas gdy sam tekst "SET NOCOUNT ON" ma aż 14 bajtów. Kiedyś myślałem, że 123 row(s) affected został zwrócony z serwera w postaci zwykłego tekstu w oddzielnym pakiecie sieciowym, ale tak nie jest. W rzeczywistości jest to mała struktura o nazwie DONE_IN_PROC osadzona w odpowiedzi. Nie jest to oddzielny pakiet sieciowy, więc nie marnuje się żadnych podróży w obie strony.

Myślę, że możesz trzymać się domyślnego liczenia zachowanie prawie zawsze bez martwienia się o wydajność. Istnieją jednak przypadki, w których wcześniejsze obliczenie liczby wierszy wpłynęłoby na wydajność, na przykład kursor tylko do przodu. W takim przypadku NOCOUNT może być koniecznością. Poza tym absolutnie nie ma potrzeby podążania za mottem "używaj NOCOUNT tam, gdzie to możliwe".

Oto bardzo szczegółowa analiza nieistotności ustawienia SET NOCOUNT: http://daleburnett.com/2014/01/everything-ever-wanted-know-set-nocount/

 169
Author: Sedat Kapanoglu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-19 21:24:02

Szukanie prawdziwych benchmarków wokół NOCOUNT Zajęło mi sporo czasu, więc pomyślałem, że podzielę się krótkim podsumowaniem.

  • Jeśli Twoja procedura składowana używa kursora do wykonywania wielu bardzo szybkich operacji bez zwracanych wyników, wyłączenie NOCOUNT może potrwać około 10 razy dłużej niż włączenie. 1 to najgorszy scenariusz.
  • Jeśli Twoja procedura składowana wykona tylko jedną szybką operację bez zwracanych wyników, ustawienie NOCOUNT na spowoduje zysk około 3% wzrost wydajności. 2 byłoby to zgodne z typową procedurą wstawiania lub aktualizacji.
  • Jeśli Twoja procedura składowana zwróci wyniki (tzn. wybierzesz coś), różnica wydajności zmniejszy się proporcjonalnie do rozmiaru zestawu wyników.
 74
Author: StriplingWarrior,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-29 21:13:52
  • Gdy ustawione NOCOUNT jest włączone, liczba (określająca liczbę wierszy, na które wpływa polecenie Transact-SQL) nie jest zwracana. Gdy ustawione NOCOUNT jest wyłączone, licznik jest zwracany. Jest on używany z dowolną instrukcją SELECT, INSERT, UPDATE, DELETE.

  • Ustawienie SET NOCOUNT jest ustawiane w czasie wykonania lub uruchomienia, a nie w czasie parse.

  • Ustaw NOCOUNT na poprawia wydajność procedury składowanej (SP).

  • Składnia: SET NOCOUNT { ON / OFF }

Przykład ustawienia NOCOUNT na:

Tutaj wpisz opis obrazka

Przykład wyłączonego ustawienia NOCOUNT:

Tutaj wpisz opis obrazka

 49
Author: Bhaumik Patel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-14 16:20:26

Myślę, że do pewnego stopnia jest to problem DBA vs.developer.

Jako dev głównie, powiedziałbym, nie używaj go, chyba że absolutnie pozytywnie musisz - ponieważ korzystanie z niego może złamać twoje ADO.NET kod (zgodnie z dokumentacją firmy Microsoft).

I myślę, że jako DBA, będziesz bardziej po drugiej stronie - używaj go, gdy tylko to możliwe, chyba że naprawdę musisz zapobiec jego użyciu.

Również, jeśli twoi Programiści kiedykolwiek użyją "rekordów" zwracanych przez ADO.NET 'S ExecuteNonQuery method call, you' re in trouble if każdy używa SET NOCOUNT ON, ponieważ w tym przypadku ExecuteNonQuery zawsze zwróci 0.

Zobacz również post na blogu Petera Bromberga i sprawdź jego pozycję.

Więc to naprawdę sprowadza się do tego, kto będzie wyznaczał standardy: -)

Marc

 29
Author: marc_s,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-27 14:56:24

Jeśli mówisz, że możesz mieć różnych klientów, jak również, istnieją problemy z klasycznym ADO, jeśli SET NOCOUNT nie jest ustawiony.

To, czego doświadczam regularnie: jeśli procedura składowana wykona pewną liczbę poleceń (a tym samym zwracane są komunikaty "XXX rows affected"), ADO zdaje się tego nie obsługiwać i wyrzuca błąd "nie może zmienić właściwości ActiveConnection obiektu Recordset, który ma obiekt Command jako źródło."

Więc generalnie popieram włączam, chyba że jest naprawdę naprawdę dobry powód, żeby tego nie robić. być może znalazłeś naprawdę naprawdę dobry powód, który muszę iść i przeczytać więcej.

 11
Author: Chris J,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-13 15:52:00

Ryzykując, że wszystko będzie bardziej skomplikowane, zachęcam do nieco innej zasady do wszystkich, które widzę powyżej:

  • zawsze Ustaw NOCOUNT ONna górze proc, zanim wykonasz jakąkolwiek pracę w proc, ale również Zawsze SET NOCOUNT OFF ponownie, przed zwróceniem jakichkolwiek zestawów rekordów z przechowywanego proc.

Tak więc "zazwyczaj nocount jest włączone, z wyjątkiem sytuacji, gdy zwracasz resultset". Nie wiem, jak to może złamać dowolny kod klienta, oznacza to, że kod klienta nigdy nie potrzebuje wiedzieć cokolwiek o procach i nie jest to szczególnie uciążliwe.

 9
Author: Tao,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-22 11:03:56

Jeśli chodzi o wyzwalacze łamiące NHibernate, miałem to doświadczenie z pierwszej ręki. Zasadniczo, gdy NH wykonuje aktualizację, oczekuje pewnej liczby wierszy, których to dotyczy. Dodając SET NOCOUNT ON do wyzwalaczy, otrzymujesz liczbę wierszy z powrotem do tego, czego oczekiwał NH, naprawiając tym samym problem. Więc tak, zdecydowanie polecam wyłączenie go dla wyzwalaczy, jeśli używasz NH.

Jeśli chodzi o użycie w SPs, jest to kwestia osobistych preferencji. Zawsze wyłączałem licznik wierszy, ale potem znowu, tak czy siak nie ma mocnych argumentów.

Z innej uwagi, powinieneś naprawdę rozważyć odejście od architektury opartej na SP, wtedy nawet nie będziesz miał tego pytania.

 5
Author: zvolkov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-11 22:37:01

USTAW NOCOUNT NA; Powyższy kod zatrzyma wiadomość wygenerowaną przez silnik sql server do okna wynikowego po wykonaniu polecenia DML / DDL.

Dlaczego to robimy? Ponieważ silnik SQL server pobiera trochę zasobów, aby uzyskać status i wygenerować wiadomość, jest on uważany za przeciążenie serwera Sql engine.So włączamy komunikat o braku kont.

 1
Author: Subhransu Panda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-18 17:34:56

Nie wiem, jak przetestować SET NOCOUNT pomiędzy Klientem a SQL, więc przetestowałem podobne zachowanie dla innych poleceń SET "SET poziom izolacji transakcji READ UNCIMMITTED"

Wysłałem polecenie z mojego połączenia zmieniające domyślne zachowanie SQL( read COMMITTED) i zostało zmienione dla kolejnych poleceń. Kiedy zmieniłem poziom izolacji wewnątrz procedury składowanej, nie zmieniło to zachowania połączenia dla następnego polecenia.

Current wniosek,

  1. Zmiana ustawień wewnątrz procedury składowanej nie zmienia domyślnych ustawień połączenia.
  2. Zmiana ustawień poprzez wysyłanie poleceń za pomocą ADOCOnnection zmienia domyślne zachowanie.

Myślę, że jest to istotne dla innych poleceń SET, takich jak "SET NOCOUNT ON"

 0
Author: Rabia Mansour,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-17 06:51:32
SET NOCOUNT ON;

Ta linia kodu jest używana w SQL, aby nie zwracać wierszy liczb, których dotyczy zapytanie. Jeśli nie wymagamy liczby wierszy, których to dotyczy, możemy użyć tej opcji, ponieważ pomogłoby to w oszczędzaniu pamięci i zwiększyłoby szybkość wykonywania zapytania.

 0
Author: user1509,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-17 09:01:40

If (set no count== off)

{ następnie będzie przechowywać dane o tym, ile rekordów dotkniętych więc zmniejsz wydajność } else { nie będzie śledził zapisów zmian dlatego popraw perfomace } }

 0
Author: Shubham Sharma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-08 11:26:01

Wiem, że to dość stare pytanie. ale tylko dla aktualizacji.

Najlepszym sposobem użycia "SET NOCOUNT ON" jest umieszczenie go jako pierwszej instrukcji w SP i ponowne wyłączenie tuż przed ostatnią instrukcją SELECT.

 0
Author: KRules,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-05 11:30:24