Úvod k výkonu
Výkon databáze je rozsáhlé a složité téma zahrnující celou sadu komponent: databázi, síť, ovladač databáze a vrstvy přístupu k datům, jako je EF Core. Vrstvy vysoké úrovně a O/RM, jako je EF Core, sice výrazně zjednodušují vývoj aplikací a zlepšují jejich udržovatelnost, ale někdy mohou být neprůhledné a skrývat vnitřní podrobnosti důležité pro výkon, jako je například spouštění SQL. V této části se pokusíme poskytnout přehled o tom, jak dosáhnout dobrého výkonu pomocí EF Core a jak se vyhnout běžným nástrahám, které mohou výkon aplikace snížit.
Identifikace kritických bodů a měření
Jako vždy v případě výkonu je důležité nespěchat na optimalizaci bez dat, která ukazují problém. Jak řekl velký Donald Knuth: „Předčasná optimalizace je kořenem všeho zla“. V části o diagnostice výkonu jsou popsány různé způsoby, jak pochopit, kde vaše aplikace tráví čas v databázové logice a jak určit konkrétní problematické oblasti. Po identifikaci pomalého dotazu lze zvážit řešení: Chybí vaší databázi index? Měli byste vyzkoušet jiné vzory dotazování?
Vždy benchmarkujte kód a možné alternativy sami – část věnovaná diagnostice výkonu obsahuje ukázkový benchmark s BenchmarkDotNet, který můžete použít jako šablonu pro vlastní benchmarky. Nepředpokládejte, že obecné, veřejně dostupné benchmarky platí v nezměněné podobě pro váš konkrétní případ použití. Na to, které řešení je nejlepší, může mít zásadní vliv řada faktorů, jako je latence databáze, složitost dotazu a skutečné množství dat v tabulkách. Mnoho veřejných benchmarků se například provádí za ideálních síťových podmínek, kdy je latence do databáze téměř nulová, a s extrémně nenáročnými dotazy, které na straně databáze nevyžadují téměř žádné zpracování (nebo vstupně-výstupní operace disku). Tyto testy jsou sice cenné pro porovnání režie modulu runtime různých vrstev přístupu k datům, ale rozdíly, které odhalují, se v reálných aplikacích, kde databáze vykonává skutečnou činnost a latence k databázi je významným faktorem výkonu, obvykle ukazují jako zanedbatelné.
Aspekty výkonu přístupu k datům
Celkový výkon přístupu k datům lze rozdělit do následujících obecných kategorií:
- Čistý výkon databáze. U relační databáze překládá EF dotazy LINQ aplikace do příkazů SQL, které jsou prováděny databází. Tyto příkazy SQL samy o sobě mohou běžet více či méně efektivně. Správný index na správném místě může znamenat zásadní rozdíl ve výkonu SQL nebo přepsání dotazu LINQ může způsobit, že EF vygeneruje lepší dotaz SQL.
- Přenos dat přes síť. Stejně jako u každého síťového systému je důležité omezit množství dat přenášených tam a zpět. To zahrnuje zajištění toho, abyste odesílali a načítali jenom data, která budete skutečně potřebovat, ale také zamezení takzvaného efektu „kartézské exploze“ při načítání souvisejících entit.
- Doby odezvy sítě. Kromě množství dat, která putují tam a zpět, se jedná o doby odezvy sítě, protože doba potřebná k provedení dotazu v databázi může být krátká v porovnání s dobou, po kterou pakety putují tam a zpět mezi vaší aplikací a databází. Režie doby odezvy hodně závisí na vašem prostředí. Čím dále je váš databázový server, tím vyšší je latence a tím nákladnější je každá doba odezvy. S nástupem cloudu se aplikace stále častěji ocitají dále od databáze a náročné aplikace, které provádějí příliš mnoho dob odezvy, zaznamenávají zhoršený výkon. Proto je důležité přesně pochopit, kdy vaše aplikace kontaktuje databázi, kolik dob odezvy provádí a jestli lze tento počet minimalizovat.
- Režie modulu runtime EF. Samotný EF také přidává k databázovým operacím určitou režii modulu runtime: EF musí zkompilovat vaše dotazy z LINQ na SQL (ačkoli by to mělo být normálně provedeno pouze jednou), sledování změn přidává určitou režii (ale může být vypnuto) atd. V praxi bude režie EF pro reálné aplikace ve většině případů pravděpodobně zanedbatelná, protože v celkovém čase převažuje doba provádění dotazů v databázi a síťová latence. Je ovšem důležité pochopit, jaké máte možnosti a jak se vyhnout některým úskalím.
Zjistěte, co se děje na pozadí
EF umožňuje vývojářům soustředit se na obchodní logiku tím, že generuje SQL, materializuje výsledky a provádí další úlohy. Jako každá vrstva nebo abstrakce má také tendenci skrývat to, co se děje na pozadí, například skutečné prováděné dotazy SQL. Výkon nemusí být nutně kritickým aspektem každé aplikace, ale v aplikacích, kde tomu tak je, je nezbytné, aby vývojář pochopil, co pro něj EF dělá: kontrolovat odchozí dotazy SQL, sledovat doby odezvy, aby se ujistil, že nedochází k problému N+1 atd.
Mezipaměť mimo databázi
Nejefektivnějším způsobem interakce s databází je nemít s ní vůbec žádnou interakci. Jinými slovy, pokud se přístup k databázi projevuje jako kritický bod výkonu aplikace, může se vyplatit ukládat určité výsledky do mezipaměti mimo databázi, aby se minimalizovaly požadavky. I když ukládání do mezipaměti zvyšuje složitost, je obzvláště důležitou součástí každé škálovatelné aplikace: Zatímco aplikační vrstvu lze snadno škálovat přidáním dalších serverů, aby zvládla zvýšenou zátěž, škálování databázové vrstvy je obvykle mnohem složitější.