Вдохновленный этим вопросом, где существуют разные взгляды на SET NOCOUNT ...
Должны ли мы использовать SET NOCOUNT ON для SQL Server? Если нет, то почему нет?
Что это делает Править 6, 22 июля 2011
Он подавляет сообщение «затронутые xx строки» после любого DML. Это набор результатов, и при отправке клиент должен его обработать. Это крошечный, но измеримый (см. Ответы ниже)
Для триггеров и т. Д. Клиент получит несколько «затронутых хх строк», и это приведет к всевозможным ошибкам для некоторых ORM, MS Access, JPA и т. Д. (См. Правки ниже)
Задний план:
Общепринятой практикой (я думал до этого вопроса) является использование SET NOCOUNT ON
в триггерах и хранимых процедурах в SQL Server. Мы используем его повсюду, и быстрый гугл показывает, что многие MVP SQL Server тоже согласны.
MSDN говорит, что это может сломать .net SQLDataAdapter .
Теперь, для меня это означает, что SQLDataAdapter ограничен исключительно простой обработкой CRUD, потому что он ожидает, что сообщение «затронет n строк» совпадает. Итак, я не могу использовать:
- ЕСЛИ СУЩЕСТВУЕТ, чтобы избежать дубликатов (сообщение не затрагивает строки) Примечание: используйте с осторожностью
- ГДЕ НЕ СУЩЕСТВУЕТ (меньше строк, чем ожидалось
- Отфильтруйте тривиальные обновления (например, данные не изменяются)
- Сделайте любой доступ к таблице раньше (например, ведение журнала)
- Скрыть сложность или денормализация
- и т.д
В вопросе marc_s (кто знает его SQL) говорит: не используйте его. Это отличается от того, что я думаю (и я тоже считаю себя достаточно компетентным в SQL).
Возможно, я что-то упускаю (не стесняйтесь указывать на очевидное), но что вы, ребята, там думаете?
Примечание: прошло много лет с тех пор, как я видел эту ошибку, потому что в настоящее время я не использую SQLDataAdapter.
Редактирует после комментариев и вопросов:
Изменить: больше мыслей ...
У нас есть несколько клиентов: один может использовать C # SQLDataAdaptor, другой может использовать nHibernate из Java. На них можно воздействовать по-разному SET NOCOUNT ON
.
Если вы рассматриваете хранимые процедуры как методы, то будет неправильно (анти-паттерн) предполагать, что некоторая внутренняя обработка работает определенным образом для ваших собственных целей.
Редактировать 2: триггер, ломающий вопрос nHibernate , где SET NOCOUNT ON
не может быть установлен
(и нет, это не дубликат этого )
Редактировать 3: Еще больше информации, благодаря моему коллеге MVP
- KB 240882 , проблема, приводящая к отключению в SQL 2000 и более ранних версиях
- Демонстрация прироста производительности
Изменить 4: 13 мая 2011
Ломает Linq 2 SQL тоже когда не указано?
Изменить 5: 14 июня 2011
Разбивает JPA, сохраненный процесс с табличными переменными: поддерживает ли JPA 2.0 табличные переменные SQL Server?
Изменить 6: 15 августа 2011
Сетка данных «Редактировать строки» SSMS требует SET NOCOUNT ON: триггер обновления с помощью GROUP BY
Изменить 7: 07 марта 2013
Более подробные сведения от @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-know-set-nocount/источник
DONINPROC
(RPC) илиDONE
(BATCH) передается в потоковом режиме сrowcount
установленными на затронутые строки, аdone_count
флаг -true
независимо от того,NO_COUNT
есть лиON
. Зависит от реализации клиентской библиотеки в тех случаях, когда запрос содержит операторы SELECT или вызовы RPC, которые действительно выбирают, может потребоваться отключить подсчет ... Когда отключено, строки по-прежнему подсчитываются для оператора выбора, но флагDONE_COUNT
установлен вfalse
. Всегда читайте то, что предлагает ваша клиентская библиотека, поскольку она будет интерпретировать поток токенов (сообщений) вместо васМне потребовалось много копать, чтобы найти реальные контрольные цифры по NOCOUNT, поэтому я решил поделиться кратким резюме.
источник
SET NOCOUNT OFF;
и поэтому они думают, что не получают дополнительные байты в ответ. Точный тест будет использоватьсяSET NOCOUNT ON
в левой иSET NOCOUNT OFF
правой хранимой процедуре. Таким образом, вы получите пакет TDS сDONEINPROC (SET NOCOUNT ...)
, снова десятьDONEINPROC (INSERT statement)
, а затемRETURNVALUE(@@ROWCOUNT)
, затемRETURNSTATUS 0
для sp и окончательноDONPROC
. Ошибка есть, потому что второй sp не имеет SET NOCOUNT OFF в теле!Когда параметр SET NOCOUNT включен, счетчик (указывающий на количество строк, затронутых оператором Transact-SQL) не возвращается. Когда SET NOCOUNT выключен, счет возвращается. Он используется с любым оператором SELECT, INSERT, UPDATE, DELETE.
Настройка SET NOCOUNT устанавливается во время выполнения или выполнения, а не во время анализа.
SET NOCOUNT ON улучшает производительность хранимых процедур (SP).
Синтаксис: SET NOCOUNT {ON | OFF}
Пример SET NOCOUNT ON:
Пример SET NOCOUNT OFF:
источник
Я полагаю, в какой-то степени это проблема DBA против разработчика.
Как разработчик в основном, я бы сказал, что не используйте его, если вам абсолютно не нужно - потому что его использование может нарушить ваш код ADO.NET (как задокументировано Microsoft).
И я думаю, как администратор базы данных, вы были бы на другой стороне - используйте его всегда, когда это возможно, если вы действительно не должны предотвращать его использование.
Кроме того, если ваши разработчики когда-либо используют «RecordsActed», возвращаемый
ExecuteNonQuery
вызовом метода ADO.NET , у васSET NOCOUNT ON
возникнут проблемы, если все будут использовать, поскольку в этом случае ExecuteNonQuery всегда будет возвращать 0.Также посмотрите сообщение в блоге Питера Бромберга и проверьте его позицию.
Так что это действительно сводится к тому, кто устанавливает стандарты :-)
Марк
источник
Если вы говорите, что у вас могут быть и другие клиенты, есть проблемы с классическим ADO, если для SET NOCOUNT не установлено значение ON.
Одна проблема, с которой я сталкиваюсь регулярно: если хранимая процедура выполняет несколько операторов (и, следовательно, возвращается количество сообщений «затронуты строки xxx»), ADO, похоже, не справляется с этим и выдает ошибку «Невозможно изменить свойство ActiveConnection объекта Recordset» который имеет объект Command в качестве источника. "
Поэтому я обычно рекомендую включить его, если только нет действительно веской причины не делать этого. Возможно, вы нашли действительно очень вескую причину, на которую мне нужно пойти и прочитать больше.
источник
Рискуя усложнить ситуацию, я призываю немного другое правило ко всем тем, что я вижу выше:
NOCOUNT ON
в верхней части процедуры, прежде чем выполнять какую-либо работу в процедуре, но также всегдаSET NOCOUNT OFF
снова, прежде чем возвращать какие-либо наборы записей из хранимой процедуры.Так что «обычно не включайте учетную запись, кроме случаев, когда вы на самом деле возвращаете набор результатов». Я не знаю, каким образом это может сломать любой клиентский код, это означает, что клиентскому коду никогда не нужно ничего знать о внутренних процессах, и это не особенно обременительно.
источник
Что касается триггеров, нарушающих NHibernate, у меня был этот опыт из первых рук. По сути, когда NH делает UPDATE, он ожидает определенного числа затронутых строк. Добавляя SET NOCOUNT ON к триггерам, вы возвращаете количество строк обратно к ожидаемому NH, тем самым устраняя проблему. Так что да, я бы определенно рекомендовал отключить его для триггеров, если вы используете NH.
Что касается использования в SP, это вопрос личных предпочтений. Я всегда выключал отсчет строк, но опять же, в любом случае нет никаких веских аргументов.
С другой стороны, вам стоит подумать об отходе от архитектуры на основе SP, тогда у вас даже не возникнет этот вопрос.
источник
Я хотел убедиться, что «SET NOCOUNT ON» не сохраняет ни сетевой пакет, ни передачу туда и обратно
Я использовал тест SQLServer 2017 на другом хосте (я использовал виртуальную машину)
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
Затем я отслеживал пакеты на порту 1433 с помощью инструмента «Wireshark»: кнопка «фильтр захвата» -> «порт 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 не был запросом
Так что, вероятно, хорошая привычка еще ...
источник
Эта строка кода используется в SQL, чтобы не возвращать количество строк, затронутых при выполнении запроса. Если нам не требуется число затронутых строк, мы можем использовать это, так как это поможет сэкономить память и увеличить скорость выполнения запроса.
источник
УСТАНАВЛИВАЙТЕ NOCOUNT ON; Приведенный выше код остановит сообщение, сгенерированное механизмом сервера sql, в окно результатов с фронтом после выполнения команды DML / DDL.
Почему мы это делаем? Поскольку движок SQL-сервера требует некоторого ресурса для получения статуса и генерации сообщения, это рассматривается как перегрузка для движка Sql-сервера. Поэтому мы устанавливаем сообщение без учета.
источник
Одно место, которое
SET NOCOUNT ON
действительно может помочь, - это когда вы делаете запросы в цикле или курсоре. Это может добавить много сетевого трафика.Включение статистики клиента в SSMS, прогон
EXEC NoCountOn
иEXEC NoCountOff
показывает, что на NoCountOff был дополнительный трафик 390 КБ:Вероятно, не идеально, чтобы делать запросы в цикле или курсоре, но мы не живем и в идеальном мире :)
источник
Я знаю, что это довольно старый вопрос. но только для обновления.
Лучший способ использовать «SET NOCOUNT ON» - это поместить его в качестве первого оператора в SP и снова установить OFF перед самым последним оператором SELECT.
источник
Функция SET NOCOUNT ON даже позволяет получить доступ к соответствующим строкам:
Полученные результаты
Сообщения
источник
Я не знаю, как проверить SET NOCOUNT ON между клиентом и SQL, поэтому я протестировал аналогичное поведение для другой команды SET "SET TRANSACTION ISOLATION LEVEL READ UNCIMMITTED"
Я отправил команду из моего соединения, меняющую поведение SQL по умолчанию (READ COMMITTED), и она была изменена для следующих команд. Когда я изменил уровень ISOLATION внутри хранимой процедуры, он не изменил поведение соединения для следующей команды.
Текущее заключение,
Я думаю, что это относится к другим командам SET, таким как "SET NOCOUNT ON"
источник
NOCOUNT
если (не задавать счет == выкл)
{тогда он сохранит данные о количестве затронутых записей, поэтому снизит производительность} иначе {он не будет отслеживать запись изменений, следовательно, улучшит производительность}}
источник
Иногда даже самые простые вещи могут иметь значение. Одним из таких простых элементов, которые должны быть частью каждой хранимой процедуры, является
SET NOCOUNT ON
. Эта строка кода, расположенная в верхней части хранимой процедуры, отключает сообщения, которые SQL Server отправляет обратно клиенту после выполнения каждого оператора T-SQL. Это выполняется для всехSELECT
,INSERT
,UPDATE
иDELETE
заявления. Наличие этой информации удобно, когда вы запускаете инструкцию T-SQL в окне запроса, но когда выполняются хранимые процедуры, нет необходимости передавать эту информацию клиенту.Удаление этих дополнительных служебных данных из сети может значительно повысить общую производительность вашей базы данных и приложения.
Если вам все еще нужно получить количество строк, на которые влияет оператор T-SQL, который выполняется, вы все равно можете использовать эту
@@ROWCOUNT
опцию. ВыпускSET NOCOUNT ON
функции this (@@ROWCOUNT
) все еще работает и может использоваться в ваших хранимых процедурах для определения количества строк, затронутых оператором.источник