Предпочтительны ли хранимые процедуры CLR по сравнению с хранимыми процедурами TSQL в SQL 2005+?

мое текущее представление-нет, предпочитаю хранимые процедуры Transact SQL, потому что они имеют меньший вес и (возможно) более высокую производительность, в то время как процедуры CLR позволяют разработчикам получать все виды озорства.

однако недавно мне нужно было отладить некоторые очень плохо написанные TSQL хранимые процессы. Как обычно, я нашел много проблем из-за оригинального разработчика-разработчика, не имеющего реального опыта TSQL, они были ASP.NET / c# focused.

Итак, используя CLR процедуры, во-первых, предоставляют гораздо более знакомый набор инструментов для этого типа разработчиков, а во-вторых, средства отладки и тестирования являются более мощными (т. е. Visual Studio вместо SQL Management Studio).

Мне было бы очень интересно услышать ваш опыт, как это кажется, это не простой выбор.

12 ответов


есть места как для хорошо написанного, хорошо продуманного T-SQL, так и для CLR. Если какая-либо функция вызывается не часто и для нее требуются расширенные процедуры в SQL Server 2000, CLR может быть опцией. Кроме того, такие вещи, как расчет рядом с данными, могут быть привлекательными. Но решение проблемы плохих программистов путем внедрения новых технологий звучит как плохая идея.


хранимые процедуры CLR не предназначены для замены запросов на основе наборов. Если вам нужно запросить базу данных, вам все равно нужно будет поместить SQL в код среды CLR, как если бы он был встроен в обычный код. Это было бы пустой тратой сил.

хранимые процедуры CLR предназначены для двух основных вещей: 1) взаимодействие с ОС, например, чтение из файла или удаление сообщения в MSMQ, и 2) выполнение сложных вычислений, особенно когда у вас уже есть код, написанный в Язык .NET для выполнения вычисления.


хостинг среды CLR в SQL Server предназначен для разработчиков баз данных более гибкие варианты в том, как они стремились выполнить задачи. Как и другие упоминали, SQL отлично подходит для операций и модификаций на наборы данных. Любой, кто сделал обширную большую разработку приложений со сложными правилами бизнеса / домена, скорее всего, скажет вам-попытка применить некоторые из этих правил с помощью чистого SQL (несколько раз в один макрос-запрос) может получить действительно кошмарный.

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

только один пример, мы часто используем хранимые процессы CLR здесь как " шлюз" для динамических поисковых запросов. Скажем, запрос поиска, который может иметь до 30 различных параметров поиска. Очевидно, что пользователи не используют все 30 из них, поэтому переданная структура данных будет иметь 30 параметров, но в основном DBNULL. Клиентская сторона имеет не вариант для создания динамического оператора по очевидным причинам безопасности. Результирующее динамическое утверждение генерируется внутри без страха перед внешними "дополнениями".


В общем случае вы используете CLR, если у вас есть что-то, что не нужно много взаимодействовать с базой данных. Предположим, вы анализируете или декодируете значение. Это проще сделать в среде CLR, а затем вернуть значение.

пытаюсь сделать запрос, произведенная в CLR-это просто не выход.

кстати, это тоже не изменилось в 2008 году.


Я считаю, что эти два не эквивалентны... подходят друг к другу.
предполагается, что интеграция CLR завершает "расширенные хранимые процедуры" прошлого. у нас есть некоторые из них на рабочем месте... по сути, блоки обработки / логики над данными SQL, которые было слишком сложно / невозможно сделать с помощью обычных хранимых процедур DB / T SQL. Поэтому они написали его как расширенные хранимые процедуры в DLL C++, которые могут быть вызваны аналогичным образом. теперь они были свернуты и интеграция CLR является заменой

  • хранимые процедуры DB: если это можно сделать в T SQL хранимых процедурах, сделайте это.
  • хранимые процедуры CLR: если логика слишком сложна или утомительна для выполнения через T SQL... если его что-то, что займет меньше строк кода CLR для его решения (манипуляция строками, сложная/пользовательская сортировка или фильтрация и т. д.) используйте этот подход.

помимо доступа к файловой системе (где CLR procs имеет очень выраженное преимущество), я бы использовал T-SQL procs. Если у вас есть особенно сложные вычисления, вы можете поместить эту часть в CLR функции и вызовите это из вашего proc (udf, где я нашел интеграцию CLR, действительно сияет). Затем вы получаете преимущества интеграции CLR для этой конкретной части вашей задачи, но сохраняете как можно больше сохраненной логики proc в БД.


учитывая то, что вы сказали, я бы предпочел, чтобы вы должным образом обучили deveopers t-SQl и базам данных в целом, чем позволяли им создавать гораздо больший ущерб производительности, позволяя им выполнять задачи t-sql в CLRs. Разработчики, которые не разбираются в базах данных, используют это как предлог, чтобы не делать то, что лучше всего для производительности базы данных, потому что они хотят использовать то, что они считают более простым маршрутом.


это всегда сводится к правильному инструменту для работы, поэтому это действительно зависит от того, что вы пытаетесь выполнить.

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

CLR procs велики и имеют свое место, но их использование должно быть исключением, а не правилом.


книги SQL Server в Интернете страница по теме перечислены эти преимущества:

  • лучшая модель программирования. языки .NET Framework во многих отношениях богаче Transact-SQL, предлагая конструкции и возможности, ранее недоступные разработчикам SQL Server. Разработчики также могут использовать возможности библиотеки .NET Framework, которая предоставляет обширный набор классов, которые могут использоваться быстро и эффективно решайте задачи программирования.

  • улучшенная безопасность. управляемый код выполняется в среде выполнения на общем языке, размещенной в Database Engine. SQL Server использует это для обеспечения более безопасной и надежной альтернативы расширенным хранимым процедурам, доступным в более ранних версиях SQL Server.

  • возможность определения типов данных и агрегатных функций. пользовательские типы и пользовательские агрегаты-это два новых объекта управляемой базы данных, которые расширяют возможности хранения и запросов SQL Server.

  • модернизированное развитие через унифицированную окружающую среду. разработка баз данных интегрирована в будущие выпуски среды разработки Microsoft Visual Studio .NET. Разработчики используют те же инструменты для разработки и отладки объектов и сценариев базы данных, что и для написания среднеуровневой или клиентской .NET Framework компоненты и услуги.

  • потенциал для повышения производительности и масштабируемости. во многих ситуациях модели компиляции и выполнения языка .NET Framework обеспечивают улучшенную производительность по сравнению с Transact-SQL.


мы столкнулись с ситуацией с функцией CLR, которая вызывалась тысячи раз в обычном SQL proc. Это был прок для импорта данных из другой системы. Функция проверила данные и обработала нули.

Если мы сделали операцию в TSQL, proc закончил примерно за 15 секунд. Если мы использовали функцию CLR, то proc закончил в 20-40 минутах. Функция CLR выглядела более элегантной, но, насколько мы могли судить, для каждого использования функция CLR. Поэтому, если у вас есть большая операция с использованием одной функции CLR, это нормально, так как время запуска мало по сравнению со временем для операции. Или, если вы вызываете функцию CLR скромное количество раз, общее время запуска для всех вызовов функции будет небольшим. Но будьте осторожны с петлями.

кроме того, для ремонтопригодности лучше не иметь больше языков, чем вам действительно нужно.


Я бы добавил несколько причин использовать CLR, которые, возможно, не были упомянуты.

  • замените и расширьте основные функции запроса, не-запроса и скалярного sql.
    A) отчеты об ошибках и оповещения могут быть интегрированы на основе определенных требований. B) легко определить уровни отладки. C) включить более простой способ взаимодействия с иностранными серверами SQL
  • переместить устаревший код в управляемую среду.

я опубликовал следующий ответ на аналогичный вопрос:преимущество SQL SERVER CLR. Я добавлю здесь, что C# / VB.net / etc будучи языком, кому-то более комфортно, чем T-SQL должен не быть причиной использования SQLCLR над T-SQL. Если кто-то не знает, как выполнить что-то в T-SQL, сначала попросите помощи в поиске решения T-SQL. Если он не существует, затем перейдите по маршруту CLR.


СРЕДЕ SQLCLR ПАРАМЕТРА / CLR Интеграция в SQL Server - это еще один инструмент для решения определенных (не всех) проблем. Есть несколько вещей, которые он делает лучше, чем то, что можно сделать в чистом T-SQL, и есть некоторые вещи, которые можно сделать только через SQLCLR. Я написал статью для SQL Server Central,лестница к уровню 1 SQLCLR: что такое SQLCLR? (бесплатная регистрация требуется для чтения статей там), что касается этого вопроса. Основы (см. связанную Статью для подробности):

  • потоковые табличные функции (sTVF)
  • динамический SQL (в пределах функции)
  • лучший доступ к внешним ресурсам / замена xp_cmdshell
    • передача данных проще
    • получение нескольких столбцов результирующего набора проще
    • нет внешних зависимостей (напр. 7zip.exe)
    • лучшая безопасность через олицетворение
  • возможность Мульти-нить
  • обработка ошибок (в пределах функции)
  • Пользовательские Агрегатов
  • Пользовательские Типы
  • изменить состояние (внутри функции и без OPENQUERY / OPENROWSET)
  • выполнить хранимую процедуру (только для чтения; внутри функции, и без OPENQUERY / OPENROWSET)
  • быстродействие (Примечание: это не смысл во всех случаях, но, безусловно, в некоторых случаях, в зависимости от типа и сложности операция)
  • может захватывать вывод (т. е. то, что отправляется на вкладку "Сообщения" в SSMS) (например,PRINT и RAISERROR С тяжести = от 0 до 10) - я забыл упомянуть об этом в статье ;-).

еще одна вещь, которую следует учитывать, иногда полезно иметь возможность обмениваться кодом между приложением и БД, чтобы БД имела представление о определенной бизнес-логике без необходимости создавать пользовательские внутренние экраны только для доступа к этому приложению код. Например, я работал над системой, которая импортировала файлы данных от клиентов и использовала пользовательский хэш большинства полей и сохраняла это значение в строке в БД. Это позволило легко пропускать строки при повторном импорте их данных, так как приложение будет хэшировать значения из входного файла и сравнивать с хэш-значением, хранящимся в строке. Если они были те же самые, то мы сразу поняли, что ни одно из полей не изменилось, поэтому мы перешли к следующему ряду, и это было простое сравнение INT. Но этот алгоритм для выполнения хэша был только в коде приложения, поэтому для отладки случая клиента или поиска способов выгрузки некоторой обработки на серверные службы, помечая строки, которые имели по крайней мере одно поле с изменениями (изменения, поступающие из нашего приложения, а не искать изменения в более новом файле импорта), я ничего не мог сделать. Это была бы отличная возможность иметь довольно простой бит бизнес-логики в БД, даже если бы не для нормальной обработки; имея что суммы закодированного значения в БД без возможности понять его значение значительно затрудняет решение проблем.

если интересно увидеть некоторые из этих возможностей в действии без необходимости писать какой-либо код, бесплатная версия SQL# (из которых я автор) имеет функции регулярных выражений, пользовательские агрегаты (UDAs), пользовательские типы (UDTs) и т. д.