Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Sok esetben a modellezés módja jelentős hatással lehet az alkalmazás teljesítményére; míg a megfelelően normalizált és "helyes" modell általában jó kiindulópont, a valós alkalmazásokban néhány pragmatikus kompromisszum hosszú utat jelenthet a jó teljesítmény eléréséhez. Mivel elég nehéz megváltoztatni a modellt, ha egy alkalmazás éles környezetben fut, érdemes szem előtt tartani a teljesítményt a kezdeti modell létrehozásakor.
Denormalizálás és gyorsítótárazás
A denormalizálás az a gyakorlat, amely redundáns adatokat ad hozzá a sémához, általában azért, hogy a lekérdezések során ne legyen összekapcsolás. Például egy blogokat és bejegyzéseket tartalmazó modell esetében, ahol minden bejegyzés rendelkezik értékeléssel, előfordulhat, hogy gyakran kell megjelenítenie a blog átlagos minősítését. Ennek egyszerű megközelítése csoportosítaná a bejegyzéseket a blogjuk szerint, és kiszámítaná az átlagot a lekérdezés részeként; ehhez azonban költséges csatlakozásra van szükség a két tábla között. A denormalizálás hozzáadná az összes bejegyzés számított átlagát egy új oszlophoz a Blogban, hogy azonnal elérhető legyen, csatlakozás vagy számítás nélkül.
A fentiek tekinthetők egyfajta gyorsítótárazásnak – a hozzászólások összesített információi a blogjukon kerülnek gyorsítótárazásra; mint minden gyorsítótárazás esetében, a probléma az, hogyan lehet a gyorsítótárazott értéket naprakészen tartani a gyorsítótárazott adatokkal. Sok esetben rendben van, ha a gyorsítótárazott adatok egy kicsit elkésnek; például a fenti példában általában ésszerű, hogy a blog átlagos minősítése egy adott ponton sem legyen teljesen naprakész. Ha ez a helyzet, akkor bármikor újraszámíthatja; ellenkező esetben egy részletesebb rendszert kell beállítani a gyorsítótárazott értékek naprakészen tartásához.
Az alábbiakban részletezünk néhány technikát a denormalizálás és gyorsítótárazás témakörében az EF Core-ban, és utalunk a dokumentáció vonatkozó szakaszaira.
Tárolt számított oszlopok
Ha a gyorsítótárazandó adatok ugyanazon tábla más oszlopainak szorzatai, akkor a tárolt számított oszlopok tökéletes megoldást jelenthetnek. Előfordulhat például, hogy vannak CustomerFirstName és LastName oszlopok, de előfordulhat, hogy az ügyfél teljes neve alapján kell keresnünk. Az adatbázis automatikusan karbantart egy tárolt számított oszlopot – amely a sor módosításakor újraszámítja –, és akár indexet is definiálhat rajta a lekérdezések felgyorsítása érdekében.
Gyorsítótároszlopok frissítése a bemenetek változásakor
Ha a gyorsítótárazott oszlopnak a tábla során kívülről származó bemenetekre kell hivatkoznia, nem használhat számított oszlopokat. Az oszlop azonban továbbra is újraszámítható, amikor a bemenet megváltozik; Például újraszámíthatja az átlagos blog minősítését minden alkalommal, amikor egy bejegyzést módosítanak, hozzáadnak vagy eltávolítanak. Mindenképpen azonosítsa a pontos feltételeket, amikor újraszámításra van szükség, ellenkező esetben a gyorsítótárazott érték nem lesz szinkronizálva.
Ennek egyik módja, ha a frissítést saját maga hajtja végre a szokásos EF Core API-val.
SaveChanges
Az események vagy elfogók segítségével automatikusan ellenőrizheti, hogy a bejegyzések frissülnek-e, és így hajthatja végre az újraszámítást. Vegye figyelembe, hogy ez általában további adatbázis-kerekítésekkel jár, mivel további parancsokat kell küldeni.
A perf-bizalmasabb alkalmazások esetében az adatbázis-eseményindítók definiálhatók az újraszámítás automatikus végrehajtásához az adatbázisban. Ez menti a további adatbázis-kerekítéseket, automatikusan ugyanabban a tranzakcióban történik, mint a fő frissítés, és egyszerűbb lehet beállítani. Az EF nem biztosít konkrét API-t az eseményindítók létrehozásához vagy karbantartásához, de teljesen rendben van egy üres migrálás létrehozása és az eseményindító definíciójának hozzáadása nyers SQL-en keresztül.
Materializált/indexelt nézetek
A materializált (vagy indexelt) nézetek hasonlóak a normál nézetekhez, azzal a kivételekkel, hogy adataik lemezen vannak tárolva ("materialized"), ahelyett, hogy minden alkalommal kiszámítanák, amikor lekérdezik a nézetet. Ezek a nézetek elméletileg hasonlóak a tárolt számított oszlopokhoz, mivel gyorsítótárazzák a potenciálisan költséges számítások eredményeit; azonban egyetlen oszlop helyett egy teljes lekérdezés eredményhalmazát gyorsítótárazzák. A materializált nézetek ugyanúgy lekérdezhetők, mint bármely normál tábla, és mivel lemezen gyorsítótárazzák őket, az ilyen lekérdezések nagyon gyorsan és olcsón hajthatók végre anélkül, hogy folyamatosan el kellene végezniük a nézetet meghatározó lekérdezés költséges számításait.
A materializált nézetek egyedi támogatása adatbázisonként eltérő. Egyes adatbázisokban (pl. PostgreSQL) a materializált nézeteket manuálisan kell frissíteni ahhoz, hogy az értékeiket szinkronizálni lehessen az alapul szolgáló táblákkal. Ez általában időzítőn keresztül történik – olyan esetekben, amikor bizonyos adatelmaradás elfogadható –, vagy egy eseményindító vagy egy tárolt eljáráshívás útján, meghatározott feltételek mellett. Az SQL Server indexelt nézetei viszont automatikusan frissülnek a mögöttes táblák módosításakor; Ez biztosítja, hogy a nézet mindig a legújabb adatokat jelenik meg a lassabb frissítések árán. Emellett az SQL Server indexnézetei különböző korlátozásokkal rendelkeznek az általuk támogatottakra; további információért tekintse meg a dokumentációt .
Az EF jelenleg nem biztosít konkrét API-t nézetek létrehozásához vagy karbantartásához, materializált/indexelt vagy egyéb módon; de teljesen rendben van , ha üres migrálást hoz létre, és nyers SQL-en keresztül adja hozzá a nézetdefiníciót.
Öröklési leképezés
Javasoljuk, hogy a szakasz folytatása előtt olvassa el a dedikált oldalt az öröklésről .
Az EF Core jelenleg három módszert támogat egy öröklési modell relációs adatbázishoz való leképezéséhez:
- Hierarchiánkénti tábla (TPH), amelyben az osztályok teljes .NET-hierarchiája egyetlen adatbázistáblára van leképezve.
- Table-per-type (TPT), amelyben a .NET-hierarchia minden egyes típusa egy másik táblára van leképezve az adatbázisban.
- Table-per-concrete-type (TPC), amelyben a .NET-hierarchia minden egyes betontípusa egy másik táblára van leképezve az adatbázisban, ahol minden tábla a megfelelő típus összes tulajdonságához tartalmaz oszlopokat.
Az öröklés-leképezési technika kiválasztása jelentős hatással lehet az alkalmazás teljesítményére – ajánlott körültekintően mérni, mielőtt véglegesítené a választást.
Intuitív módon a TPT úgy tűnhet, mint a "tisztább" technika; Minden .NET-típushoz külön tábla teszi az adatbázissémát a .NET-típushierarchiához hasonlóvá. Emellett mivel a TPH-nak egyetlen táblában kell a teljes hierarchiát képviselnie, a sorokban az összes oszlop található, függetlenül attól, hogy milyen típusú a sor, és a nem kapcsolódó oszlopok mindig üresek és nem használhatók. A "tisztátalannak" tűnő leképezési technika mellett sokan úgy vélik, hogy ezek az üres oszlopok jelentős helyet foglalnak el az adatbázisban, és a teljesítmény is sérülhet.
Jótanács
Ha az adatbázisrendszer támogatja (e.g. SQL Kiszolgáló), akkor érdemes lehet a ritkán fellelhető TPH-oszlopokhoz "ritka oszlopokat" használni.
A mérés azonban azt mutatja, hogy a TPT a legtöbb esetben a teljesítmény szempontjából rosszabb leképezési technika; ha a TPH összes adata egyetlen táblából származik, a TPT-lekérdezéseknek több táblát kell összekapcsolniuk, és az illesztések a relációs adatbázisok teljesítményproblémáinak egyik elsődleges forrásai. Az adatbázisok általában jól kezelik az üres oszlopokat, és az olyan funkciók, mint az SQL Server ritka oszlopai , még tovább csökkenthetik ezt a többletterhelést.
A TPC teljesítményjellemzői hasonlóak a TPH-hoz, de kissé lassabb, ha minden típusú entitást kiválaszt, mivel ez több táblát is magában foglal. A TPC azonban igazán kiválóan alkalmas egyetlen levéltípusú entitások lekérdezésére – a lekérdezés csak egyetlen táblát használ, és nincs szükség szűrésre.
Konkrét példaként tekintse meg ezt a teljesítménytesztet , amely egy egyszerű modellt állít be egy 7-típusú hierarchiával; Minden típushoz 5000 sor kerül – összesen 35000 sor – és a teljesítményteszt egyszerűen betölti az adatbázis összes sorát:
| Metódus | Jelent | Hiba | StdDev | Gen 0 | Gen 1 | Kiosztott |
|---|---|---|---|---|---|---|
| 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 |
Mint látható, a TPH és a TPC lényegesen hatékonyabb, mint a TPT ebben a forgatókönyvben. Vegye figyelembe, hogy a tényleges eredmények mindig az adott lekérdezés végrehajtásától és a hierarchiában lévő táblák számától függenek, így más lekérdezések eltérő teljesítménybeli eltérést mutathatnak; Javasoljuk, hogy ezt a teljesítményteszt-kódot sablonként használja más lekérdezések teszteléséhez.