2012-02-13 9 views
30

Mam dziwne zachowanie próbując wykonać zapytanie deklarujące ObjectQuery MergeOption na "NoTracking", w tym przypadku struktura encji nie powinna dołączać żadnej jednostki i nie tworzyć względnego ObjectStateEntry do śledzenia stanu obiektu.Entge Framework Mergeoption notracking bad performance

Problem polega na tym, że zamiast zwiększyć wydajność jeszcze gorzej, to samo zapytanie trwa jakieś 10 sekund z domyślną mergeoption (czyli AppendingOnly) i większych 1 minuty, jeśli staram się określić notracking

Czy ktoś ma wyjaśnienie tego?

+0

Jak zmierzyłeś wykonywanie zapytań? –

+0

zasadniczo biorąc znacznik czasu przed i po kwerendzie wykonanej za pomocą ToList() – MaRuf

+0

Ale ile razy wykonujesz zapytanie i jaką kolejność wykonywania używasz? –

Odpowiedz

100

Jeśli wyłączysz śledzenie zmian, ustawiając opcję scalania NoTracking, oszczędzasz koszty związane z dołączaniem obiektów do kontekstów, ale z drugiej strony tracisz także zarządzanie tożsamością.

Oznacza to, że potencjalnie znacznie więcej obiektów - wiele z tym samym kluczem - zostanie zmaterializowanych.

Przykład: załóżmy, że mamy obiekt User z kolekcją Roles jako właściwość nawigacji. Załóżmy również, że masz 1 milion użytkowników w bazie danych, a wszyscy użytkownicy mają te same 10 ról, czyli każdy użytkownik ma kolekcję ról z 10 elementami. Jeżeli uruchomić następujące zapytanie ...

var users = context.Users.Include("Roles").ToList(); 

... liczba zmaterializowanych i wystąpienia obiektów zależy od opcji Merge:

  • Jeśli nie używać NoTracking będziesz miał 1.000 .010 obiektów w pamięci, a mianowicie 1 milion użytkowników, ale tylko 10 ról, ponieważ mapowanie tożsamości zapewni, że tylko 1 rola na klucz zostanie zmaterializowana i dołączona do kontekstu. Te same 10 instancji ról są używane dla wszystkich kolekcji użytkownika Roles użytkownika.

  • Jeśli jednak używasz , EF nie będzie dołączać obiektów do kontekstu, dlatego zarządzanie tożsamością jest wyłączone i będziesz mieć 11.000.000 obiektów w pamięci: 1 milion użytkowników i 10 instancji roli na użytkownika, tj. 10 milionów obiekty ról. Tak więc masz ponad 10 razy więcej zmaterializowanych obiektów niż wtedy, gdy obiekty są dołączone do kontekstu.

Object materializacja jest sklasyfikowana "moderate" performace costs:

Operation: materializacji przedmiotów
Przybliżony koszt: Umiarkowane
Cykl imprezy: raz dla każdego obiektu, które są zwracane zapytania .

Uwagi: Proces odczytu zwrócony obiekt DbDataReader i tworzenia obiektów i ustawiania wartości właściwości, które oparte są o wartości podane w każde wystąpienie klasy DbDataRecord.Jeśli obiekt już istnieje w ObjectContext i kwerendy używa AppendOnly lub PreserveChanges opcji Merge, etap ten nie wpływa na wydajność.

Innymi słowy: Jeśli zapytanie korzysta z opcji NoTracking scalania, ten etap wpływa na wydajność i może to być możliwe, że korzyści wydajnościowe śledzenie zmian niepełnosprawnych są niszczone przez wad niepełnosprawnych zarządzania tożsamością i zwielokrotniona materializacja obiektu.

+1

Przykład jest bardzo jasny! Wspaniały! – kingkong0924

+3

(powolne klaśnięcie) Aaaa i dlatego masz 70k punktów. dobra robota. – SteveCav