Состояние триггеров CLR - PullRequest
1 голос
/ 14 июня 2011

Я рассматриваю использование триггера CLR вместо традиционного T-SQL, потому что мне нужно использовать некоторую логику, которая уже реализована в C #. Я знаю, что SQL-сервер поддерживает интеграцию с CLR, и в моем случае это решение, которое стоит попробовать.

Однако операции, которые я хочу выполнить, могут быть несколько медленными. Не достаточно медленный, чтобы полностью исключить их использование в инициируемых действиях, но, вероятно, заметно медленный, когда дело доходит до вставки сотен тысяч записей. Самая медленная часть может сильно выиграть от кеширования, я полагаю, что будет очень мало кешей и тысячи попаданий в кеш. На этом этапе все это приводит к вопросу: могут ли триггеры CLR иметь какое-либо состояние? И, что более важно, каков жизненный цикл этого состояния?

Полагаю, я мог бы использовать статические поля класса триггера для хранения некоторого состояния, но я понятия не имею, когда оно инициализируется (когда сервер запускается? При запуске транзакции? Не указано?). Я не уверен, является ли это безопасным маршрутом, и поэтому спрашиваю, какова общая практика использования некоторых состояний в триггерах CLR (если есть).

Чтобы избежать путаницы: мне нужно кэшировать объекты CLR , а не результаты некоторых запросов SQL, поэтому речь идет не о том, насколько хорош сам SQL Server в кэшировании, я хочу кэшировать некоторые данные, которые не ' принадлежит базе данных. Кроме того, я рассматриваю CLR не потому, что не могу выполнять строковые операции и проверку границ в T-SQL. Мне нужно выполнить некоторую логику, которая реализована в библиотеке классов CLR и имеет много зависимостей. Стоит ли использовать триггеры в этом случае - это другой вопрос, который почти не имеет к этому отношения.

Большое спасибо заранее.

PS: Буду признателен за любые комментарии и идеи по теме, даже те, которые не отвечают на мой вопрос напрямую, но, пожалуйста, не делайте все о том, что "триггеры - это зло и не должны когда-либо использоваться "и" интеграция CLR медленная и главная проблема совместимости ". Кроме того, я знаю, что кому-то это может показаться «преждевременной оптимизацией», но сейчас я просто хочу знать, какие у меня варианты оптимизации, так как я новичок в интеграции CLR в SQL-сервер. Я не буду оптимизировать его, если результаты профилирования не предполагают этого, но я не хочу реализовывать все это, чтобы понять, что это слишком медленно, и я ничего не могу с этим поделать.

Я использую SQL Server 2008 и .NET 3.5.

1 Ответ

0 голосов
/ 08 апреля 2016

Хотя можно использовать поля класса static в классе триггера SQLCLR для кэширования значений, есть несколько вещей, с которыми вам нужно очень быть осторожными:

  1. Сколько данных вы планируете кэшировать? Вы не хотите занимать слишком много памяти, которую SQL Server должен вместо этого использовать для запросов.

  2. Существует один домен приложений на базу данных на владельца сборки (т. Е. AUTHORIZATION на сборке). Это означает, что код в любой конкретной сборке является общим для всех сеансов SQL Server (т.е. SPID). Если данные являются просто поисковыми данными, которые не изменятся в зависимости от того, какой процесс взаимодействует со статическим полем, то это нормально. Но если данные отличаются для каждого процесса, это приведет к «странному» поведению, если вы не свяжете значение, такое как текущий TransactionID, с процессом.

  3. Если данные относятся к процессу, если вы найдете способ дифференциации каждого конкретного SPID / SESSION, как вы собираетесь очистить старые данные? Он будет существовать в памяти до тех пор, пока явно не будет удален или домен приложения не будет выгружен. Это не проблема для общих данных поиска, которые предназначены для совместного использования всеми, так как этот тип данных не увеличивается с каждым новым процессом. Но данные для каждого процесса будут постоянно увеличиваться, если не будут удалены.

  4. Домены приложений могут быть выгружены в любое время и по разным причинам (нехватка памяти, сброс / повторное создание сборки, изменение безопасности, связанное со сборкой, изменение безопасности, связанное с БД, запуск DBCC FREESYSTEMCACHE('ALL') и т. Д. ). Если кэшируемые данные могут вызывать разные результаты между последовательными процессами, если один процесс полагается на данные, кэшированные предыдущим процессом, то это не может быть гарантировано работающим. Если сброс кеша между процессами приводит только к необходимости перезагрузить кеш, тогда все должно быть в порядке.

Другие заметки (но не к чему быть осторожными):

  1. Домены приложений загружаются при вызове первого метода в сборке, где в настоящее время не существует AppDomain для базы данных, в которой существует сборка, и пользователя, который является авторизатором этой сборки.

  2. Домены приложений будут оставаться загруженными до тех пор, пока они не будут выгружены SQL Server по одной из указанных выше причин, но ни один из этих сценариев не обязательно произойдет. Это означает, что домен AppDomain может оставаться загруженным в течение очень долгого времени (т.е. до перезапуска сервера / службы).

  3. Каждая сборка загружается при первом обращении к методу внутри нее.

  4. Чтобы использовать событие загрузки, вы можете поместить код в конструкцию статического класса. Просто имейте в виду, что SqlContext не доступно, поэтому вы не можете сделать SqlConnection в конструкторе статического класса, который использует внутрипроцессное соединение контекста (т.е. Context Connection = true).

...