Wprowadzenie do wydajności

Wydajność bazy danych to obszerny i złożony temat obejmujący cały stos składników: baza danych, sieć, sterownik bazy danych i warstwy dostępu do danych, takie jak EF Core. Chociaż warstwy wysokiego poziomu i maszyny O/RM, takie jak EF Core, znacznie upraszczają tworzenie aplikacji i zwiększają łatwość konserwacji, czasami mogą być nieprzezroczyste, ukrywając szczegóły wewnętrzne krytyczne dla wydajności, takie jak wykonywany program SQL. Ta sekcja próbuje przedstawić przegląd sposobu osiągnięcia dobrej wydajności za pomocą programu EF Core oraz sposobu unikania typowych pułapek, które mogą obniżyć wydajność aplikacji.

Identyfikowanie wąskich gardeł i mierzenie, mierzenie, mierzenie

Tak jak zawsze w przypadku wydajności, ważne jest, aby nie spieszyć się z optymalizacją bez danych wskazujących na problem; jak powiedział kiedyś wielki Donald Knuth: "Przedwczesna optymalizacja jest źródłem wszelkiego zła". W sekcji diagnostyki wydajności omówiono różne sposoby zrozumienia, gdzie aplikacja spędza czas w logice bazy danych i jak wskazać konkretne problematyczne obszary. Po zidentyfikowaniu powolnego zapytania można rozważyć rozwiązania: czy w bazie danych brakuje indeksu? Czy należy wypróbować inne wzorce zapytań?

Zawsze testuj kod i możliwe alternatywy samodzielnie — sekcja diagnostyki wydajności zawiera przykładowy test porównawczy z benchmarkDotNet, którego można użyć jako szablonu dla własnych testów porównawczych. Nie zakładaj, że ogólne publiczne testy porównawcze mają zastosowanie as-is do konkretnego przypadku użycia; Różne czynniki, takie jak opóźnienie bazy danych, złożoność zapytań i rzeczywiste ilości danych w tabelach, mogą mieć głęboki wpływ na to, które rozwiązanie jest najlepsze. Na przykład wiele publicznych testów porównawczych jest wykonywanych w idealnych warunkach sieciowych, w których opóźnienie bazy danych jest prawie zerowe i z bardzo lekkimi zapytaniami, które prawie nie wymagają przetwarzania (lub we/wy dysku) po stronie bazy danych. Chociaż są one przydatne do porównywania obciążeń środowiska uruchomieniowego różnych warstw dostępu do danych, różnice, które ujawniają, zwykle są niewielkie w rzeczywistej aplikacji, gdzie baza danych wykonuje rzeczywistą pracę i opóźnienia w bazie danych jest znaczącym czynnikiem wydajności.

Aspekty wydajności dostępu do danych

Ogólną wydajność dostępu do danych można podzielić na następujące szerokie kategorie:

  • Czysta wydajność bazy danych. W przypadku relacyjnej bazy danych program EF tłumaczy zapytania LINQ aplikacji na instrukcje SQL wykonywane przez bazę danych; te instrukcje SQL mogą działać wydajniej lub bardziej wydajnie. Właściwy indeks we właściwym miejscu może mieć wpływ na wydajność sql lub ponowne zapisywanie zapytania LINQ może sprawić, że platforma EF wygeneruje lepsze zapytanie SQL.
  • Transfer danych sieciowych. Podobnie jak w przypadku dowolnego systemu sieciowego, ważne jest, aby ograniczyć ilość danych wysyłanych i odbieranych w sieci. Obejmuje to zapewnienie wysyłania i ładowania tylko potrzebnych danych, ale także unikanie tak zwanego efektu "eksplozji kartezjańskiej" podczas ładowania powiązanych jednostek.
  • Rundy sieciowe. Poza ilością danych przesyłanych tam i z powrotem, ważne są również podróże w obie strony w sieci, ponieważ czas potrzebny na wykonanie zapytania w bazie danych może być przytłoczony przez czas podróży pakietów tam i z powrotem między aplikacją a bazą danych. Narzut związany z przesyłaniem danych w obie strony w dużym stopniu zależy od twojego środowiska; im dalej znajduje się serwer bazy danych, tym większe jest opóźnienie i bardziej kosztowny każdy cykl przesyłania danych. Wraz z pojawieniem się chmury, aplikacje coraz częściej znajdują się dalej od bazy danych, a "gadatliwe" aplikacje, które wykonują zbyt wiele zapytań, doświadczają pogorszenia wydajności. Dlatego ważne jest, aby dokładnie zrozumieć, kiedy aplikacja kontaktuje się z bazą danych, ile wykonuje rund, i czy tę liczbę można zminimalizować.
  • Obciążenie związane ze środowiskiem uruchomieniowym ef. Na koniec sama platforma EF dodaje pewne obciążenie związane ze środowiskiem uruchomieniowym do operacji bazy danych: program EF musi skompilować zapytania z linQ do języka SQL (chociaż powinno to być wykonywane tylko raz), śledzenie zmian dodaje pewne obciążenie (ale można je wyłączyć) itp. W praktyce obciążenie platformy EF dla rzeczywistych aplikacji może być niewielkie w większości przypadków, ponieważ czas wykonywania zapytań w bazie danych i opóźnienia sieci zdominował łączny czas; ale ważne jest, aby zrozumieć, jakie są opcje i jak uniknąć niektórych pułapek.

Dowiedz się, co dzieje się pod kapturem

Program EF umożliwia deweloperom skoncentrowanie się na logice biznesowej przez generowanie kodu SQL, materializowanie wyników i wykonywanie innych zadań. Podobnie jak każda warstwa lub abstrakcja, ma również tendencję do ukrywania tego, co dzieje się pod maską, na przykład rzeczywistych zapytań SQL wykonywanych. Wydajność niekoniecznie jest krytycznym aspektem każdej aplikacji, ale w aplikacjach, w których tak jest, ważne jest, aby deweloper zrozumiał, co EF robi dla nich: sprawdzaniu wychodzących zapytań SQL, śledzenie powrotów danych, aby upewnić się, że problem N+1 nie występuje itp.

Pamięć podręczna poza bazą danych

Na koniec najbardziej efektywnym sposobem interakcji z bazą danych jest brak interakcji z nią w ogóle. Innymi słowy, jeśli dostęp do bazy danych pojawia się jako wąskie gardło wydajności w aplikacji, warto zapisywać pewne wyniki w pamięci podręcznej poza bazą danych, aby zminimalizować żądania. Chociaż buforowanie zwiększa złożoność, jest to szczególnie kluczowa część każdej skalowalnej aplikacji: podczas gdy warstwa aplikacji może być łatwo skalowana przez dodanie dodatkowych serwerów do obsługi zwiększonego obciążenia, skalowanie warstwy bazy danych jest zwykle znacznie bardziej skomplikowane.