2012-12-18 23 views
5

Mam tabelę z 200 000 rekordów, gdzie otrzymuję tylko pierwszą 10 używając .Take(), ale pobranie danych zajmuje około 10 sekund.Linq do encji jest bardzo powolny za pomocą metody .Take()

Moje pytanie brzmi: czy metoda .Take() pobiera wszystkie dane z bazy danych i filtruje 10 najlepszych po stronie klienta?

Oto mój kod:

mylist = (from mytable in db.spdata().OrderByDescending(f => f.Weight) 
            group feed by mytable.id into g 
            select g.FirstOrDefault()).Take(10).ToList(); 

spdata() jest funkcja importu z procedury przechowywanej.

Dzięki

+7

Jeśli jesteś ciekawy, co działa na bazie należy zaczepić profilera do DB i sprawdź dzienniki, to najlepszy sposób, aby się tego dowiedzieć. – Chris

+1

Jeśli spdata() zwróci 200 000, to tak, zrobi to po stronie klienta. –

+0

Oprócz metody Chrisa można również wypróbować Linqpad i przełączyć się do widoku SQL po napisaniu zapytania, aby zobaczyć wygenerowany SQL, lub wstawić punkt przerwania (za pomocą tej metody http://stackoverflow.com/questions/1412863/how -do-i-view-the-sql-generated-by-the-entity-framework), aby zobaczyć, co jest generowane podczas wykonywania programu. –

Odpowiedz

8

Procedura składowana prawdopodobnie zwraca bardzo dużo danych do klienta, co jest bardzo powolne. Nie można zdalnie skierować zapytania do sproc. Byłoby to możliwe przy użyciu widoku lub funkcji wycenionej w tabeli.

Nie ma możliwości użycia sprocu w zapytaniu. Możesz go wykonać tylko sam.

Twoim zamiarem było prawdopodobnie wykonanie na serwerze serwera Take(10). Aby to działało, musisz przełączyć się do zapytania wbudowanego, widoku lub TVF.

6

Metoda rozszerzenie Take robi nie pobrać wszystkie wyniki z bazy danych. Tak nie działa Take.

Jednak Twoja rozmowa db.spdata() prawdopodobnie pobiera wszystkie wiersze.

1

nie jestem w 100% pewien, ale jak pamiętam masz IEnumerable rezultat kiedy wezwać SP przy użyciu EF DataContext ...

Istnieje kilka było zoptymalizować wydajność:

  • Przekaż kryteria wyszukiwania s jako parametry SP i wykonaj filtrowanie w procedurze przechowywanej.

Lub jeśli masz dość proste zapytanie w SP gdzie nie uznającej żadnych zmiennych i gdzie jesteś po prostu łączącą kilka tabel następnie:

  • Załóż indeksowany widok, w którym należy określić kwerendę, która cię potrzebujesz i wywołaj metodę Take na tym.
    Co to daje? Możesz mapować do utworzonego widoku, a EF będzie zwracał wynik IQueryable, a nie IEnumerable. To zoptymalizuje polecenie sql, a raczej odbiera wszystkie dane, a następnie pobiera 10 wymaganych elementów, a następnie zostanie utworzone polecenie sql, które właśnie pobiera 10 elementów.

Ja również radzę, aby zobaczyć, jaka jest różnica między IEnumerable a IQueryable.

0

Dzieje się tak, ponieważ przed sortowaniem dane są sortowane, co nie jest możliwe w SQL.

należy użyć kruszywa, aby uzyskać najwyższą wagę z każdej grupy, a następnie posortować ciężary, aby uzyskać dziesięć największych:

mylist = (
    from mytable in db.spdata() 
    group feed by mytable.id into g 
    select g.Max(f => f.Weight) 
).OrderByDescending(w => w).Take(10).ToList(); 
+0

Wystąpił błąd Błąd "Lokalna zmienna o nazwie" g "nie może być zadeklarowana w tym zakresie, ponieważ nadałaby ona inne znaczenie" g ", która jest już używana w" macierzystym lub bieżącym zakresie "w celu oznaczenia czegoś innego" –

+0

@AliIssa: Tak, musi to być inna zmienna. Zmieniłem to. – Guffa