Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
I många fall kan ditt sätt att modellera ha en djupgående inverkan på programmets prestanda. även om en korrekt normaliserad och "korrekt" modell vanligtvis är en bra utgångspunkt, kan vissa pragmatiska kompromisser i verkliga program gå långt för att uppnå bra prestanda. Eftersom det är ganska svårt att ändra din modell när ett program körs i produktion är det värt att ha prestanda i åtanke när du skapar den första modellen.
Denormalisering och cachelagring
Avormalisering är en metod för att lägga till redundanta data i schemat, vanligtvis för att eliminera sammanfogningar vid frågeställningar. För en modell med bloggar och inlägg, där varje inlägg har ett omdöme, kan du till exempel behöva visa det genomsnittliga omdömet för bloggen ofta. Den enkla metoden för detta skulle gruppera inläggen efter deras blogg och beräkna medelvärdet som en del av frågan. men detta kräver en kostsam koppling mellan de två tabellerna. Avormalisering skulle lägga till det beräknade genomsnittet för alla inlägg i en ny kolumn på Blog, så att det är omedelbart tillgängligt, utan att man behöver ansluta eller beräkna.
Ovanstående kan ses som en form av cachelagring – aggregerad information från inläggen cachelagras på deras blogg; Och precis som vid cachelagring är problemet hur du håller det cachelagrade värdet uppdaterat med de data som cachelagras. I många fall är det OK att cachelagrade data släpar efter en stund. I exemplet ovan är det till exempel vanligtvis rimligt att bloggens genomsnittliga omdöme inte är helt uppdaterat vid en viss tidpunkt. Om så är fallet kan du omberäkna det då och då. Annars måste ett mer detaljerat system konfigureras för att hålla de cachelagrade värdena uppdaterade.
Följande beskriver några tekniker för avnormalisering och cachelagring i EF Core och pekar på relevanta avsnitt i dokumentationen.
Lagrade beräknade kolumner
Om de data som ska cachelagras är en produkt av andra kolumner i samma tabell kan en lagrad beräknad kolumn vara en perfekt lösning. Till exempel kan en Customer ha FirstName och LastName kolumner, men vi kan behöva söka efter kundens fullständiga namn. En lagrad beräknad kolumn underhålls automatiskt av databasen – som beräknar om den när raden ändras – och du kan till och med definiera ett index över den för att påskynda frågor.
Uppdatera cachekolumner när indata ändras
Om din cachelagrade kolumn behöver referera till indata utanför tabellens rad kan du inte använda beräknade kolumner. Det är dock fortfarande möjligt att beräkna om kolumnen när dess indata ändras. Du kan till exempel beräkna om den genomsnittliga bloggens omdöme varje gång ett inlägg ändras, läggs till eller tas bort. Var noga med att identifiera de exakta villkoren när omberäkning behövs, annars kommer det cachelagrade värdet att bli osynkroniserat.
Ett sätt att göra detta är att utföra uppdateringen själv via det vanliga EF Core-API:et.
SaveChanges
Händelser eller interceptorer kan användas för att automatiskt kontrollera om några inlägg uppdateras och för att utföra omberäkningen på det sättet. Observera att detta vanligtvis innebär ytterligare databasrundturer eftersom ytterligare kommandon måste skickas.
För mer perf-känsliga program kan databasutlösare definieras för att automatiskt utföra omberäkningen i databasen. Detta sparar de extra databasrundorna, sker automatiskt inom samma transaktion som huvuduppdateringen och kan vara enklare att konfigurera. EF tillhandahåller inget specifikt API för att skapa eller underhålla utlösare, men det är helt okej att skapa en tom migrering och lägga till utlösardefinitionen via rå SQL.
Materialiserade/indexerade vyer
Materialiserade (eller indexerade) vyer liknar vanliga vyer, förutom att deras data lagras på disk ("materialiserade"), i stället för att beräknas varje gång vyn efterfrågas. Sådana vyer liknar begreppsmässigt lagrade beräknade kolumner, eftersom de cachelagrar resultatet av potentiellt dyra beräkningar. De cachelagra dock en hel frågas resultatuppsättning i stället för en enda kolumn. Materialiserade vyer kan efterfrågas precis som alla vanliga tabeller, och eftersom de cachelagras på disken körs sådana frågor mycket snabbt och billigt utan att ständigt behöva utföra de dyra beräkningarna av frågan som definierar vyn.
Specifikt stöd för materialiserade vyer varierar mellan databaser. I vissa databaser (t.ex. PostgreSQL) måste materialiserade vyer uppdateras manuellt för att deras värden ska kunna synkroniseras med deras underliggande tabeller. Detta görs vanligtvis via en timer – i fall där viss datafördröjning är acceptabel – eller via en utlösare eller ett lagrat proceduranrop under specifika förhållanden. SQL Server-indexerade vyer uppdateras å andra sidan automatiskt när deras underliggande tabeller ändras. Detta säkerställer att vyn alltid visar de senaste data, på bekostnad av långsammare uppdateringar. Dessutom har SQL Server-indexvyer olika begränsningar för vad de stöder. Mer information finns i dokumentationen .
EF tillhandahåller för närvarande inte något specifikt API för att skapa eller underhålla vyer, materialiserade/indexerade eller på annat sätt. men det går bra att skapa en tom migrering och lägga till vydefinitionen via rå SQL.
Arvsmappning
Vi rekommenderar att du läser den dedikerade sidan om arv innan du fortsätter med det här avsnittet.
EF Core har för närvarande stöd för tre metoder för att mappa en arvsmodell till en relationsdatabas:
- TPH (Table-per-hierarchy ), där en hel .NET-hierarki med klasser mappas till en enskild databastabell.
- TPT (Table-per-type ), där varje typ i .NET-hierarkin mappas till en annan tabell i databasen.
- TPC (Table-per-concrete-type ), där varje betongtyp i .NET-hierarkin mappas till en annan tabell i databasen, där varje tabell innehåller kolumner för alla egenskaper av motsvarande typ.
Valet av arvsmappningsteknik kan ha stor inverkan på programmets prestanda – vi rekommenderar att du noggrant mäter innan du bestämmer dig för ett val.
Intuitivt kan TPT verka som "renare" teknik; En separat tabell för varje .NET-typ gör att databasschemat ser ut ungefär som .NET-typhierarkin. Eftersom TPH måste representera hela hierarkin i en enda tabell har rader dessutom alla kolumner oavsett vilken typ som faktiskt finns på raden, och orelaterade kolumner är alltid tomma och oanvända. Bortsett från att verka vara en "oren" kartteknik, tror många att dessa tomma kolumner tar upp betydande utrymme i databasen och kan skada prestanda också.
Tips/Råd
Om databassystemet stöder det (e.g. SQL Server) bör du överväga att använda "glesa kolumner" för TPH-kolumner som sällan fylls i.
Mätningen visar dock att TPT i de flesta fall är den sämre karttekniken ur prestandasynpunkt. där alla data i TPH kommer från en enda tabell måste TPT-frågor sammanfoga flera tabeller och kopplingar är en av de primära källorna till prestandaproblem i relationsdatabaser. Databaser brukar också hantera tomma kolumner på ett bra sätt, och funktioner som glesa SQL Server-kolumner kan minska kostnaderna ytterligare.
TPC har liknande prestandaegenskaper som TPH, men är något långsammare när du väljer entiteter av alla typer eftersom det omfattar flera tabeller. TPC utmärker sig dock verkligen när du frågar efter entiteter av en enskild lövtyp – frågan använder bara en enda tabell och behöver ingen filtrering.
Ett konkret exempel finns i det här riktmärket som konfigurerar en enkel modell med en hierarki av sju typer. 5 000 rader är seedade för varje typ – totalt 3 5000 rader – och riktmärket läser helt enkelt in alla rader från databasen:
| Metod | Medelvärde | Fel | StdDev | Gen 0 | Gen 1 | Tilldelades |
|---|---|---|---|---|---|---|
| TPH | 149,0 ms | 3,38 ms | 9,80 ms | 4000.0000 | 1000.0000 | 40 MB |
| TPT | 312,9 ms | 6,17 ms | 10,81 ms | 9000.0000 | 3000.0000 | 75 MB |
| TPC | 158,2 ms | 3,24 ms | 8,88 ms | 5000.0000 | 2000.0000 | 46 MB |
Som vi kan se är TPH och TPC betydligt effektivare än TPT för det här scenariot. Observera att faktiska resultat alltid beror på vilken fråga som körs och antalet tabeller i hierarkin, så andra frågor kan visa ett annat prestandagap. Du uppmanas att använda den här benchmark-koden som mall för att testa andra frågor.