Запретить ADO.NET использовать sp_executesql - PullRequest
5 голосов
/ 11 января 2010

В нашей базе данных SQL Server 2005 (протестировано с использованием Management Studio с DBCC FREEPROCCACHE и DBCC DROPCLEANBUFFERS), следующий оператор работает быстро (время компиляции ~ 0,2 с, время выполнения ~ 0,1 с):

SELECT ... FROM ... WHERE a = 1 AND b = '' ...

Однако следующий оператор медленный (время компиляции ~ 0,2 с, 7-11 с время выполнения):

exec sp_executesql N'SELECT ... FROM ... WHERE a = @a AND b = @b ...', N'@a int, @b nvarchar(4000), ...', @a=1, @b=N'', ...

SQL Server выбирает другой план выполнения, хотя запросы совпадают. Это имеет смысл, поскольку в первом случае SQL Server имеет фактические значения a, b и все другие доступные параметры и может использовать статистику для создания лучшего плана. По-видимому, план запроса для конкретных значений параметров на намного лучше , чем общий, и определенно перевешивает любое преимущество в производительности "кэширование плана запроса".

Теперь мой вопрос: ADO.NET всегда использует второй параметр (sp_executesql) при выполнении параметризованных запросов, который обычно имеет смысл (кэширование плана запросов и т. Д.). В нашем случае, однако, это убивает производительность. Так есть ли какой-нибудь способ

  • заставляет ADO.NET использовать что-то отличное от sp_executesql (то есть то, что анализатор запросов SQL Server учитывает фактические значения параметров) ИЛИ
  • заставляет SQL Server пересчитать план запроса SQL, переданного в sp_executesql , принимая во внимание значения параметров ?

И, пожалуйста, не говорите мне, что я должен вернуться к некрасивому, старому, опасному sql = "WHERE b = " + quoteAndEscape(parameterB) ...

Помещение SQL в хранимую процедуру не имеет значения (медленно, с WITH RECOMPILE и без него). Я не публиковал фактическую статистику SQL, поскольку она довольно сложна (объединяет несколько таблиц, включая подвыборы и агрегацию).

Ответы [ 4 ]

4 голосов
/ 25 ноября 2011

Старая ветка, я знаю, но я только что нашел ее, прибегая к помощи почти той же фразы! У меня была точно такая же проблема (запрос выполнялся очень быстро в Management Studio с использованием параметров, но затем очень медленно через ADO.Net), и я повторил проблему, выполнив запрос в Management Studio через "exec sp_execute". Два плана выполнения были очень разными, даже с подсказкой Оптимизировать для запроса, поэтому вместо этого я сделал первоначальный выбор некоторых данных во временную таблицу. Это, казалось, имело значение, и, учитывая, что вы говорите, что ваш запрос сложный, он вполне может иметь значение и в вашем случае - я не совсем уверен, как он работает, но, похоже, он пнул план выполнения в строка даже при использовании sp_execute.

2 голосов
/ 01 февраля 2011

Я считаю, что проблема связана с использованием типа данных VARCHAR в базе данных. Похоже, что SQL Server не использует указанный индекс, если параметр where объявлен как NVARCHAR.

Однако вы можете изменить столбец базы данных на NVARCHAR (это, конечно, увеличит размер), и тогда производительность индекса, вероятно, улучшится.

В настоящее время у меня возникла эта проблема с LINQ, и, возможно, мне, возможно, придется вернуться к использованию хранимых процедур, чтобы обойти ее.

Эта проблема подробно объясняется в этом обсуждении Microsoft Connect

2 голосов
/ 11 января 2010

Вы можете попробовать подсказку OPTIMIZE FOR которая (цитата):

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

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

Я бы переместил запрос в хранимую процедуру, а затем в команде укажите command.CommandType = CommandType.StoredProcedure.

Это не создает sp_executesql и не увеличивает производительность

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...