Параметр SQL замедляет запрос - PullRequest
5 голосов
/ 24 октября 2011

У меня есть запрос, который я использую с SQL Server 2008R2 через ADO.NET. Когда я использую встроенное предложение LIKE, оно работает менее чем за секунду, при этом 5 строк возвращаются из 2 миллионов. Если в начале запроса в SSMS я объявляю параметр, как я это делаю в .NET, это занимает вечность.

Это тот же запрос, но параметризованный.

Первый (который отлично работает) (который прекрасно работает):

;WITH Results_CTE AS (
    SELECT  ld.* , ROW_NUMBER() OVER (ORDER BY PK_ID) AS RowNum  
    FROM list..List_Data ld 
    WHERE Name IS NOT NULL  AND 
    Postcode LIKE 'SW14 1xx%' 
) SELECT * FROM Results_CTE 

Второе, что занимает вечность:

declare @postcode varchar(10) = 'SW14 1xx'
;WITH Results_CTE AS (
    SELECT  ld.* , ROW_NUMBER() OVER (ORDER BY PK_ID) AS RowNum  
    FROM list..List_Data ld
    WHERE Name IS NOT NULL  AND 
    Postcode LIKE @postcode +'%' 
) SELECT * FROM Results_CTE 

Я считаю, что это как-то связано с внутренней работой SQL Server, но я действительно понятия не имею.

Ответы [ 4 ]

2 голосов
/ 04 декабря 2014

Я гуглил потенциальные проблемы с SqlCommand.Parameters.Add () в C #, и я нашел эту страницу.Я знаю, что это пост SQL Server, но другие могут найти его через Google, и это может помочь им с C #.

Для меня ни один из приведенных выше ответов не сработал, поэтому я попробовал другой метод.

Вместо:

cmd.Parameters.Add(new SqlParameter("@postcode", postcode));

Я использовал это вместо:

// Replace SqlDbType enumeration with whatever SQL Data Type you're using.
cmd.Parameters.Add("@postcode", SqlDbType.VarChar).Value = postcode;

И не забывайте пространство имен:

using System.Data;

Надеюсь, это кому-нибудь поможет!

2 голосов
/ 24 октября 2011

Вы можете использовать optimize for, чтобы параметризованный запрос использовал тот же план выполнения, что и план с определенным параметром:

SELECT * 
FROM Results_CTE 
OPTION (OPTIMIZE FOR (@postcode = 'SW14 1xx'))
2 голосов
/ 24 октября 2011

Использовать

SELECT * 
FROM Results_CTE 
OPTION (RECOMPILE)

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

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

1 голос
/ 24 октября 2011

Это похоже на проблему, вызванную перехватом параметров - во время компиляции плана SQL Server «вынюхивает» текущие значения параметров и использует его для оптимизации запроса.Наиболее распространенная проблема, которая может возникнуть, заключается в том, что если запрос выполняется со значением «нечетное» параметра при первом запуске / компиляции, в этом случае план запроса будет оптимизирован для этого значения параметра, однако перехват параметров может вызвать все другие проблемы.

В вашем случае, если запрос выполняется с пустым / нулевым значением для @postcode, тогда в запросе используется предложение LIKE '%', которое может вызвать сканирование таблицы в виде подстановочного знака LIKEиспользуется в начале фильтра.Похоже, либо план был изначально запущен / скомпилирован с пустым параметром @postcode, либо SQL Server каким-то образом запутался в этом параметре.

Есть несколько вещей, которые вы можете попробовать:

  1. Пометьте запрос для перекомпиляции, а затем снова запустите запрос с ненулевым значением для @postcode.
  2. «Маска» для параметра, чтобы попытаться предотвратить перехват параметров,

например:

declare @postcode varchar(10) = 'SW14 1xx'
declare @postcode_filter varchar(10) = @postcode + '%'
-- Run the query using @postcode_filter instead of @postcode

Хотя этот запрос выглядит так, как будто он должен вести себя точно так же, я обнаружил, что SQL Server обрабатывает параметры странным образом - правила, когда именно перехват параметроввремя от времени может быть немного странным, поэтому вы можете поэкспериментировать с вариантами, описанными выше.

...