2012-04-05 15 views
12

miałem na myśli an article, który koncentruje się na przyspieszaniu LINQ do zapytań SQL. Jedną z wymienionych technik jest "Użyj skompilowanych zapytań" i wyjaśnij, jak z niego korzystać.Kiedy kompilacja zapytań LINQ do SQL poprawia wydajność

Chciałem zobaczyć poprawę wydajności kompilowanych zapytań, a więc próbowałem tego samego przykładu dostarczonego przez autora. Użyłem Northwind Db jako datacontext. Próbowałem normalnego wykonania i wykonania instrukcji compiledquery i sprawdziłem je na LINQ PAD.

Najpierw próbowałem wykonać zapytanie bez używając CompileQuery. Zajęło 2.065 sekund.

var oo = from o in Orders 
    where o.OrderDetails.Any (p => p.UnitPrice > 100) 
    select o; 

oo.Dump ("Order items with unit price more than $100"); 

var oo1 = from o in Orders 
    where o.OrderDetails.Any (p => p.UnitPrice > 10) 
    select o; 

oo1.Dump ("Order items with unit price more than $10"); 

drugie zapytania z użyciem CompileQuery. Zajęło 2.100 sekund.

var oo = CompiledQuery.Compile ((TypedDataContext dc, decimal unitPrice) =>  
    from o in Orders 
    where o.OrderDetails.Any (p => p.UnitPrice > unitPrice) 
    select o 
); 

oo (this, 100).Dump ("Order items with unit price more than $100"); 
oo (this, 10).Dump ("Order items with unit price more than $10"); 

Ponowne ich wykonanie kilka razy wykazało, że czas potrzebny na oba podejścia jest prawie podobny.

Tutaj widzimy tylko dwa wykonania zapytań dla każdej metody. Próbowałem wykonać 10 zapytań dla każdego z nich. Ale obaj skończyli około 7 sekund.

Czy wstępne kompilowanie zapytań naprawdę poprawia wydajność? Czy źle rozumiem warunki użytkowania?

Dziękuję za poświęcony czas i uwagę.

Edit: Po przeczytaniu zaakceptowane odpowiedź, czytelnicy mogą także chcą przejść przez this article który ładnie wyjaśnia jak skompilowane zapytania poprawić wydajność.

Odpowiedz

10

Należy pamiętać, że istnieją dwa główne kawałki kwerendy LINQ, które mogą być szczególnie drogie:

  1. Kompilacja wyrażeń LINQ w instrukcji SQL.
  2. Uruchamianie SQL i pobierania wyników

W twoim przypadku, masz stosunkowo proste zapytanie i albo bardzo powolne połączenie z bazą danych, niektóre bardzo dużych zbiorów danych lub tabel, które nie są indeksowane w sposób optymalny sposób uruchomienia tego konkretnego zapytania. A może połączenie wszystkich trzech.

Tak więc, w porównaniu do czasu potrzebnego na utworzenie zapytania SQL (może 10-50 milisekund), drugi etap zajmuje tyle czasu (~ 1000 ms), że prawie nie można zauważyć różnicy.

można zobaczyć znaczną poprawę, jeżeli następujące warunki są prawdziwe:

  1. zapytanie LINQ jest złożony,
  2. masz szybkie połączenie z bazą danych,
  3. kwerendy SQL sama biegnie szybko w tej bazie danych i
  4. zestaw wyników jest na tyle mały, że stosunkowo szybko zostaje przeniesiony z bazy danych.

W praktyce otrzymałem zapytania, które mogą zająć do 500 ms, aby skompilować, ale tylko kilka milisekund do uruchomienia. Zazwyczaj są to przypadki, w których skupiam się na wstępnej kompilacji zapytań.

Dobrym sposobem, aby wiedzieć z wyprzedzeniem, jakie świadczenia zyskuje można oczekiwać od prekompilowanymi zapytań jest do czasu sekund instancją zapytania przy użyciu Stopwatch obiekt, a następnie uruchomić wygenerowany SQL bezpośrednio za pomocą Analizuj SQL LINQPad za cecha. Jeśli zapytanie SQL szybko się zwraca, ale kwerenda LINQ zajmuje dużo czasu, jest to dobry kandydat do wstępnego kompilowania.

+0

Oznacza to, że w przypadku dużych zapytań możemy wyeliminować wykonanie instrukcji time foreach, a następnie pomyśleć tylko o poprawieniu drugiego kroku (wykonanie i odzyskanie wyników). – Marshal

+0

@Marshal: Tak, to jest idea. – StriplingWarrior

+0

Dziękuję bardzo James. To było naprawdę pomocne. Przy okazji, lubię też czytać twoje blogi;) – Marshal