Тайм-аут ADO.NET, но работает нормально в SSMS - PullRequest
5 голосов
/ 24 октября 2011

Я пытаюсь выполнить запрос из ADO.NET с использованием SQL Server 2008R2. Я использую CTE для обеспечения подкачки и добавления параметров для @Offset и @Limit, которые являются целыми числами.

Я строю параметризованный запрос в зависимости от пользовательских данных. Окончательный результат такой:

;WITH Results_CTE AS (
    SELECT  ld.* , ROW_NUMBER() OVER (ORDER BY Key_Field) AS RowNum  
    FROM list..List_Data ld 
    WHERE VALUE_2010 IS NOT NULL  
    AND  Postcode LIKE @Postcode + '%' 
) SELECT * FROM Results_CTE 
    WHERE RowNum > @Offset AND RowNum < @Offset + @Limit 
OPTION (RECOMPILE) 

Я использую несколько подобных фраз, поэтому у меня есть OPTION RECOMPILE. Если я объявляю параметры через SSMS и запускаю так:

declare @postcode varchar(10) = 'SW1 1AA';
declare @Offset int = 0;
declare @Limit int = 10;

Я получаю очень быстрое время ответа (менее 1 с). Однако, если я попробую это с ADO.NET, это займет вечность. Я попытался добавить параметры с обоими из них:

cmd.Parameters.AddWithValue("@Offset", startRowIndex) // times out
cmd.Parameters.AddWithValue("@Limit", limit)

cmd.Parameters.Add(New SqlParameter("@Offset", SqlDbType.BigInt)) // also times out
cmd.Parameters.Item("@Offset").Value = startRowIndex
cmd.Parameters.Add(New SqlParameter("@Limit", SqlDbType.BigInt))
cmd.Parameters.Item("@Limit").Value = limit

Если в первом запросе возвращается только несколько строк, а я отбрасываю фильтрацию @Offset и @Limit, я получаю приличное время ответа. Есть ли способ, которым я могу ускорить это и использовать пейджинг?

EDIT: я передаю параметр @postcode (который является строкой в ​​.NET через это:

cmd.Parameters.AddWithValue("@Postcode", normalizedPostcode)

Ответы [ 2 ]

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

Ваш код ADO.NET передает параметр тип данных , отличный от того, который вы тестируете в SSMS, и у вас возникают неявные проблемы приведения.

Не используйте

cmd.Parameters.AddWithValue("@postcode", normalizedPostcode)

, поскольку это автоматически создаст параметр nvarchar, и вы получите неявные приведения в вашем плане выполнения, означающие, что индекс нельзя использовать. Вместо этого передайте явно созданный параметр типа varchar.

cmd.Parameters.Add("@postcode", SqlDbType.Varchar, 10)
2 голосов
/ 24 октября 2011

1) Для параметра @postcode укажите длину .

cmd.Parameters.Add("@postcode", SqlDbType.VarChar, 10).Value = str

2) Перепишите запрос:

;WITH Results_CTE AS (
    SELECT  ld.Key_Field, ROW_NUMBER() OVER (ORDER BY Key_Field) AS RowNum  
    FROM list..List_Data ld 
    WHERE VALUE_2010 IS NOT NULL  
    AND  Postcode LIKE @Postcode + '%' 
) SELECT * FROM Results_CTE a
INNER JOIN list..List_Data b ON a.Key_Field = Key_Field
WHERE RowNum > @Offset AND RowNum < @Offset + @Limit 
--OPTION (RECOMPILE) 

Примечание 1 : Я предполагаю, что Key_Field является первичным ключом (кластеризованным) для таблицы List_Data.

Примечание 2 : проверьте, есть ли у вас индекс для полей VALUE_2010 и Postcode. Если у вас SQL 2008+, вы можете создать отфильтрованный индекс:

--UNIQUE if Postcode has unique values for VALUE_2010 IS NOT NULL
CREATE [UNIQUE] INDEX aaa
ON MySchema.List_Data (Postcode)
WHERE VALUE_2010 IS NOT NULL  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...