2011-10-03 14 views
17

Mam dość proste zapytanie, które ciągle dostaję timeout (zajmie to trzy minuty, aby zakończyć, zatrzymałem go wcześniej, więc mogłem opublikować to pytanie), gdy jest uruchomiony w kodzie , jednak gdy uruchomię tę samą kwerendę z tego samego komputera w Sql Server Management Studio, kwerenda zajmie tylko 2532 ms pierwsze zapytanie, gdy dane nie są buforowane na serwerze i 524 ms dla powtarzających się kwerend.Zapytanie bardzo powolne w kodzie, ale szybkie w SSMS

Oto mój kod C#

using (var conn = new SqlConnection("Data Source=backend.example.com;Connect Timeout=5;Initial Catalog=Logs;Persist Security Info=True;User ID=backendAPI;Password=Redacted")) 
       using (var ada = new SqlDataAdapter(String.Format(@" 
SELECT [PK_JOB],[CLIENT_ID],[STATUS],[LOG_NAME],dt 
FROM [ES_HISTORY] 
inner join [es_history_dt] on [PK_JOB] = [es_historyid] 
Where client_id = @clientID and dt > @dt and (job_type > 4 {0}) {1} 
Order by dt desc" 
    , where.ToString(), (cbShowOnlyFailed.Checked ? "and Status = 1" : "")), conn)) 
{ 
    ada.SelectCommand.Parameters.AddWithValue("@clientID", ClientID); 
    ada.SelectCommand.Parameters.AddWithValue("@dt", dtpFilter.Value); 
    //ada.SelectCommand.CommandTimeout = 60; 
    conn.Open(); 
    Logs.Clear(); 
    ada.Fill(Logs); //Time out exception for 30 sec limit. 
} 

tutaj jest mój kod używam w SSMS, wyciągnąłem go bezpośrednio z ada.SelectCommand.CommandText

declare @clientID varchar(200) 
set @clientID = '138' 
declare @dt datetime 
set @dt = '9/19/2011 12:00:00 AM' 

SELECT [PK_JOB],[CLIENT_ID],[STATUS],[LOG_NAME],dt 
FROM [ES_HISTORY] 
inner join [es_history_dt] on [PK_JOB] = [es_historyid] 
Where client_id = @clientID and dt > @dt and (job_type > 4 or job_type = 0 or job_type = 1 or job_type = 4) 
Order by dt desc 

Co powoduje znaczną różnicę dla różnica w czasie?


Aby sekcja komentarzy była czysta, odpowiem na niektóre często zadawane pytania.

Ten sam komputer i logowanie są używane zarówno dla aplikacji, jak i dla ssms.

Tylko 15 wierszy jest zwracanych w moim przykładowym zapytaniu. Jednak es_history zawiera 11351699 rows i es_history_dt zawiera 8588493 rows. Obie tabele są dobrze zindeksowane, a plan wykonania w SSMS mówi, że używają indeksu do wyszukiwania, więc są to szybkie wyszukiwania. Program zachowuje się tak, jakby nie korzystał z indeksów dla wersji C# zapytania.

+0

Czy używasz tego samego użytkownika w systemie SSMS, jak w kodzie? – bzlm

+1

Ile wierszy jest zwracanych przez to zapytanie? –

+0

@hugh zobacz moją aktualizację .. –

Odpowiedz

31

Twój kod w SSMS to nie ten sam kod, który uruchamiasz w swojej aplikacji. Ta linia w aplikacji dodaje parametr nvarchar:

ada.SelectCommand.Parameters.AddWithValue("@clientID", ClientID); 

natomiast w scenariuszu SSMS deklarujesz ją jako VARCHAR:

declare @clientID varchar(200) 

związku z zasadami Data Type Precedence wyraz w zapytaniu Where client_id = @clientID nie jest SARG -able gdzie @clientID jest typu NVARCHAR (robię skok wiary i zakładam, że kolumna client_id jest typu VARCHAR). Aplikacja wymusza zatem skanowanie tabeli, w którym zapytanie SSMS może wykonać szybkie wyszukiwanie klucza. Jest to dobrze znany i zrozumiały problem związany z użyciem parametru Parameters.AddWithValue i był wcześniej omawiany w wielu artykułach, np. patrz How Data Access Code Affects Database Performance. Gdy problem jest zrozumiałe, że rozwiązania są trywialne:

fIR st rozwiązanie jest lepsze, ponieważ rozwiązuje problem zanieczyszczenia pamięci podręcznej oprócz problemu z SARG.

polecam również przeczytać Slow in the Application, Fast in SSMS? Understanding Performance Mysteries

+0

Właściwie użyłem varchar, ponieważ interfejs dla funkcji przekazał identyfikator klienta jako ciąg. Sprawdziłem schemat, a Client_ID jest rzeczywiście int. Zmiana w moim kodzie w celu przekonwertowania przekazanego ciągu na int przed wykonaniem zapytania rozwiązała problem. Dziękuję Ci! –

+0

Dziękuję również za ostatni link, jest bardzo pomocny. –

0

Uruchom profilera na C# połączenia - nie może być inna działalność dzieje, że nie jesteś świadomy.

0

Uchwyć plan wykonania z obu SSMS, gdy ręcznie uruchomisz zapytanie, a następnie z Profila, gdy używasz aplikacji. Porównać i kontrastować.

0

Uruchom DBCC FREEPROCCACHE, zgodnie z sugestią here, aby się upewnić, że problem nie wynika z nieaktualnego planu wykonania kwerendy.

Powiązane problemy