ADO.NET - różny czas wykonywania się tego samego zapytania.

0

Wykonuję tę samą metodę (która zwraca liczbę rekordów w tabeli, w tabeli jest nieco ponad 900k rekordów) 2 razy i zawsze czas wykonywania się ich jest różny. Pierwsza metoda wykonuje się kilkanaście/kilkadziesiąt razy dłużej od drugiej (np. 2331 ms i 90 ms). Dlaczego tak się dzieje? W przypadku np. wyciągania wszystkich rekordów z tabeli, różnica czasu jest już niewielka i liczy do około 10%.

static System.Diagnostics.Stopwatch watch;

static void Main(string[] args)
{
    watch = System.Diagnostics.Stopwatch.StartNew();
    new ExperimentalTableDb().GetCount();
    watch.Stop();
    Console.WriteLine(watch.ElapsedMilliseconds);

    watch = System.Diagnostics.Stopwatch.StartNew();
    new ExperimentalTableDb().GetCount();
    watch.Stop();
    Console.WriteLine(watch.ElapsedMilliseconds);
}
public class ExperimentalTableDb
{
    public int GetCount()
    {
        return Convert.ToInt32(GetExecuteScalar("SELECT COUNT(*) FROM dbo.ExperimentalTable"));
    }


    protected object GetExecuteScalar(string queryString, params KeyValuePair<string, object>[] parameters)
    {
        using (SqlConnection conn = new SqlConnection(ConnectionString))
        using (SqlCommand cmd = new SqlCommand(queryString, conn))
        {
            foreach (var parameter in parameters)
            {
                cmd.Parameters.AddWithValue(parameter.Key, parameter.Value);
            }

            conn.Open();
            return cmd.ExecuteScalar();
        }
    }
}
0

Serwer sobie optymalizuje zapytania albo keszuje wyniki itp.

0

Bo za pierwszym razem kod musi zostać skompilowany przez CLR. Dlatego też nigdy żaden poważny benchmark nie bierze pod uwagę pierwszego odwołania do metody.

0

@somekind: A jak metoda się nie zmienia (w sensie, że kod jest ten sam) i się takie rzeczy dzieją?

0

Ale co się ma zmieniać? Metoda przed pierwszym wywołaniem jest kompilowana przez środowisko uruchomieniowe z kodu pośredniego do kodu możliwego do wykonania przez procesor. Tu nie ma nad czym filozofować, tak działa JIT.

0

Mi nie o to chodzi bo pierwsze wywołanie to wiadomo. Mi chodzi o sytuację, kiedy wrzucam API na serwer. Ludzie sobie pracują na terminalach mobilnych. Wywołanie jednej metody api trwa czasem 20 s. Mimo tego ze ta metoda była już wywoływana wcześniej to czasami jest szybko a czasami (po jakiejś bezczynności) 20 sekund. Wygląda to tak, że człowiek wchodzi w jakieś okno na terminalu, dostaje dość złożony viewmodel (20 sekund). Potem coś tam sobie dłubie i kolejne wejście w to okno jest błyskawiczne, ale po np 10 minutach bezczynności wejście w to okno znowu generuje viewmodel przez 20 sekund. Wygląda to tak, jakby baza sobie keszowała wynik, po 10 minutach wywala to z kesza i następne wyciągnięcie danych trwa 20 sekund.
Ten viewmodel to zlepek z ponad 20 tabel. Legacy. Zastanawiam się nad jakimiś widokami indeksowanymi ale założę na to osobny wątek.

0

@jacek.placek: ale czemu zakładasz, że to baza muli? Może np. API jest ubijane przez IIS po określonym idle timeoucie? A może problem jest w kliencie GUI? Dla mnie baza byłaby ostatnim kandydatem na źródło tego typu problemu.

0

Spróbuj odtworzyć problem po godzinach kiedy masz mniejszy ruch w sieci pracy i zalogować ruch w pomiędzy aplikacją i bazą danych. Porównaj przy tym ile czasu mija od momentu kiedy aplikacja wchodzi do linijki, gdzie ma nastąpić odczyt z bazy, a momentem kiedy faktyczne zapytanie SQL zostaje wysłane do serwera. Jeżeli ten czas jest duży, ale tylko po większym czasie niekatywności to mi to wygląda na problem z DNSem.

0

Baza danych nie keszuje wyników, co najwyżej może trzymać w pamięci strony z danymi z tabel i one rzeczywiście mogą wypaść na dysk jak zabraknie ramu, natomiast ostateczne zwracane wyniki nie są keszowane.

1 użytkowników online, w tym zalogowanych: 0, gości: 1