Каковы ограничения SqlDependency
Я использую таблицу в качестве очереди сообщений и "подписываюсь" на получение обновлений с помощью SqlDependency. Везде, где я читаю, люди говорят, что следите за ограничениями, но конкретно не говорите, что они есть. Из того, что я понял, у вас будут проблемы, когда таблица будет иметь очень высокую частоту обновления, к счастью, я смотрю только на 10 - 20 значений в минуту максимум.
Каковы другие ограничения/влияние на SqlServer?
Ответы
Ответ 1
Наиболее полный список, который я могу найти (отсюда), выглядит следующим образом:
- Проецируемые столбцы в операторе SELECT должны быть указаны явно, а имена таблиц должны содержать имена из двух частей. Обратите внимание, что это означает, что все таблицы, на которые есть ссылки в операторе, должны находиться в одной базе данных.
- Оператор не может использовать звездочку() или имя_таблицы. синтаксис для указания столбцов.
- Оператор не может использовать безымянные столбцы или повторяющиеся имена столбцов.
- Оператор должен ссылаться на базовую таблицу.
- Оператор не должен ссылаться на таблицы с вычисляемыми столбцами.
- Проецируемые столбцы в операторе SELECT могут не содержать агрегатных выражений, если только оператор не использует выражение GROUP BY. Когда предоставляется выражение GROUP BY, список выбора может содержать агрегатные функции COUNT_BIG() или SUM(). Тем не менее, SUM() не может быть указан для столбца, допускающего значение NULL. Оператор не может указывать HAVING, CUBE или ROLLUP.
- Проецируемый столбец в операторе SELECT, который используется как простое выражение, не должен появляться более одного раза.
- Оператор не должен включать операторов PIVOT или UNPIVOT.
- Оператор не должен включать операторы UNION, INTERSECT или EXCEPT.
- Заявление не должно ссылаться на представление.
- Оператор не должен содержать ничего из следующего: DISTINCT, COMPUTE или COMPUTE BY или INTO.
- Оператор не должен ссылаться на глобальные переменные сервера (@@variable_name).
- Оператор не должен ссылаться на производные таблицы, временные таблицы или переменные таблиц.
- Оператор не должен ссылаться на таблицы или представления из других баз данных или серверов.
- Оператор не должен содержать подзапросов, внешних объединений или самостоятельных объединений.
- Оператор не должен ссылаться на большие типы объектов: текст, текст и изображение.
- Оператор не должен использовать полнотекстовые предикаты CONTAINS или FREETEXT.
- Оператор не должен использовать функции набора строк, включая OPENROWSET и OPENQUERY.
- Оператор не должен использовать ни одну из следующих агрегатных функций: AVG, COUNT (*), MAX, MIN, STDEV, STDEVP, VAR или VARP.
- Оператор не должен использовать никаких недетерминированных функций, включая функции ранжирования и управления окнами.
- Оператор не должен содержать определенные пользователем агрегаты.
- Оператор не должен ссылаться на системные таблицы или представления, включая представления каталога и представления динамического управления.
- Заявление не должно включать информацию FOR BROWSE.
- Оператор не должен ссылаться на очередь.
- Оператор не должен содержать условных операторов, которые не могут изменяться и не могут возвращать результаты (например, WHERE 1 = 0).
- Оператор не может указывать подсказку блокировки READPAST.
- Заявление не должно ссылаться на QUEUE компонента Service Broker.
- Заявление не должно ссылаться на синонимы.
- Оператор не должен иметь сравнения или выражения, основанного на двойных/реальных типах данных.
- Оператор не должен использовать выражение TOP.
Дополнительные ссылки:
Ответ 2
В дополнение к этому, если кто-либо еще подумает об использовании SqlDependency для получения уведомлений об изменениях, я использовал этот подход в производстве, и у меня проблемы с ним. Я изучаю его, чтобы увидеть, связаны ли проблемы с моим кодом, но основными проблемами являются:
-
Если вы запускаете несколько изменений в быстрой последовательности, вы не всегда получаете эквивалентное количество событий, проходящих через код. В моем коде, если две новые записи вставлены одна за другой, я получаю только одно уведомление (для последнего).
-
Невозможно узнать запись, которая была добавлена. Поэтому, если вы добавите новую запись и код начнет получать уведомление, в коде нет способа узнать идентификатор этой новой записи, поэтому вам нужно запросить базу данных для нее.
Ответ 3
Прошел день, преследуя проблему, когда SQL Service Broker не работал, основной причиной было обращение к базе данных в хранимой процедуре.
Например, этот select
отлично работает в SQL Management Studio:
select [MyColumn] from [MyDatabase].[MySchema].[MyTable]
Однако это отклоняется SQL Service Broker, потому что мы ссылаемся на базу данных в инструкции select, а обратный вызов из SqlDependency
возвращается с Invalid
в SqlNotificationEventArgs e
, см. http://msdn.microsoft.com/en-us/library/ms189308.aspx.
Изменение SQL, переданного в SqlDependency, в следующее выражение устраняет ошибку:
select [MyColumn] from [MySchema].[MyTable]
Update
Приведенный выше пример является лишь одним из многих, многих ограничений для оператора SQL, от которого зависит SQL Service Broker. Полный список ограничений см. В Каковы ограничения SqlDependency.
Причина? Оператор SQL, используемый SQL Service Broker, преобразуется за кулисами в инструкции для мониторинга журнала транзакций SQL для внесения изменений в базу данных. Этот мониторинг выполняется в ядре SQL Server, что делает его чрезвычайно быстрым, когда дело доходит до обнаружения изменений в таблице (таблицах). Однако эта скорость стоит дорого: вы не можете использовать только какой-либо оператор SQL, вы должны использовать тот, который может быть преобразован в инструкции для мониторинга SQL Transaction Войти.
Ответ 4
Обратите внимание, что вы не можете использовать подсказку nolock в хранимой процедуре, иначе зависимость будет постоянно оставаться недействительной, и поэтому любой кеш, который вы делаете на ней, будет постоянно повторно запрашивать базу данных.
with (NOLOCK)
Это не упоминается в документации (насколько я могу судить)
Перед процедурой script
требуются следующие параметры SET:
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
Другие утверждают, что эти параметры SET также требуются, но я не думаю, что они есть. Это хорошая идея, чтобы установить тогда, как это в любом случае, хотя.
SET CONCAT_NULL_YIELDS_NULL ON
SET QUOTED_IDENTIFIER ON
SET NUMERIC_ROUNDABORT OFF
SET ARITHABORT ON
Ответ 5
Еще одна большая проблема, с которой я сталкиваюсь с этой технологией: необходимость подключения к подписчику для разрешения "Создать процедуру". Уровень веб-службы моего приложения на данный момент работает как ограниченный пользователь. Чтобы получить настройку уведомлений с помощью SQLDependency, мне нужно было бы открыть этого пользователя для создания proc. Похоже, что это довольно хороший шаг по пути владения.
Ответ 6
Чтобы преодолеть эти ограничения, вы можете попробовать использовать SqlTableDependency.
Посмотрите на www.sqltabledependency.it
Ответ 7
Он использует Service Broker. Поэтому он не будет работать на неуправляемых экземплярах SQL Azure. Так что будьте осторожны, если вы используете SQL Azure или когда-либо может.
https://docs.microsoft.com/en-us/azure/sql-database/sql-database-features
Сервисный Брокер
Поддерживается отдельными базами данных и эластичными пулами:
нет
Поддерживается управляемыми экземплярами:
Да, но только в рамках инстанса. См. Различия сервисного брокера
Так что, вероятно, не подходит, если только ваша среда не может его использовать!