2011-10-24 10 views
5

Próbuję uruchomić kwerendę z ADO.NET przy użyciu SQL Server 2008R2. Używam CTE, aby zapewnić stronicowanie i dodawanie parametrów dla @Offset i @Limit, które są obie liczby całkowite.Limit czasu ADO.NET ale działa poprawnie w SSMS

Buduję sparametryzowane zapytanie w zależności od danych wejściowych użytkownika. Wyjście końcowe to:

;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) 

Używam kilka jak klauzul, dlatego mam OPTION RECOMPILE. Jeśli oświadczam parametrów za pośrednictwem SSMS i uruchomić tak:

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

uzyskać bardzo szybki czas reakcji (mniej niż 1 s). Jeśli jednak spróbuję tego z ADO.NET, zajmie to na zawsze. Próbowałem dodając parametry z obu z nich:

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 

Jeśli istnieją tylko kilka wierszy zwracanych przez pierwszego zapytania choć i upuść filtrowanie @Offset i @Limit, ja dostać przyzwoity czas reakcji. Czy jest jakiś sposób, aby przyspieszyć ten proces przy użyciu stronicowania?

EDIT: Jestem przekazując w parametrze @postcode (który jest ciągiem w .NET poprzez to:

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

@ Zamknij wyborcę. To nie jest dupe. Poprzednie pytanie dotyczyło wyjaśniania różnych zachowań za pomocą zmiennych, a nie parametrów. Oba są traktowane inaczej przez SQL Server. –

+0

Czy możesz pokazać kod, w którym przekazujesz parametr '@ postcode'? –

+0

Czy to na pewno limit czasu SQL? Nie ma żadnej możliwości, aby jego limit czasu próbował nawiązać połączenie (np. Ponieważ masz wiele połączeń otwartych wciąż, gdy to robisz) lub coś podobnego? – Chris

Odpowiedz

7

Twój kod ADO.NET przechodzi w parametrze a different datatype niż jednej jesteś testowania w SSMS i otrzymujesz ukryte problemy oddanych.

nie używaj

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

jak to zostanie automatycznie utworzyć nvarchar parametr i otrzymasz niejawne rzutowania w twoim planie wykonania, co oznacza, że ​​nie można użyć indeksu. Zamiast tego należy zamiast tego podać jawnie utworzony parametr typu varchar.

+0

Doskonała wskazówka. Dokładne dostrajanie parametrów w .NET do DBType uzyskuje mniej lub bardziej natychmiastową odpowiedź. – Echilon

2

1) Dla parametru @postcode please specify the length.

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

2) Przepisz zapytanie:

;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) 

UWAGA 1: Zakładam, że Key_Field jest kluczem podstawowym (skupione) dla List_Data tabeli.

Uwaga 2: Sprawdź, czy masz indeks na VALUE_2010 i pola kodów pocztowych. Jeśli masz SQL 2008+, możesz utworzyć filtrowany indeks:

--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 
+0

Wydaje się to poprawiać prędkość o kilka milisekund, ale jest różna. Nie zaszkodzi dla dobrej miary. – Echilon