Soha ne írja le a gyorsítótárazási megoldást

Az adatbázissal végzett munka felgyorsításának egy másik módja a korábban már kért objektumok gyorsítótárazása.

Fontos! Soha ne írjon saját gyorsítótárazási megoldást. Ennek a feladatnak annyi buktatója van, amelyekről nem is álmodott.

1. probléma – a gyorsítótár kiürítése . Néha olyan események fordulnak elő, amikor egy objektumot el kell távolítani a gyorsítótárból, vagy frissíteni kell a gyorsítótárban. Ennek egyetlen módja az, hogy az összes kérést a gyorsítótár-motoron keresztül továbbítsa az adatbázisnak. Ellenkező esetben minden alkalommal kifejezetten meg kell adnia a gyorsítótárnak, hogy mely objektumokat kell törölni vagy frissíteni.

2. probléma - memóriahiány . A gyorsítótárazás nagyszerű ötletnek tűnik mindaddig, amíg meg nem tapasztalja, hogy a memóriában lévő objektumok sok helyet foglalnak el. A kiszolgálóalkalmazás gyorsítótárának hatékony működéséhez további több tíz gigabájt memóriára van szüksége.

És mivel mindig van memóriahiány, hatékony stratégiára van szükség az objektumok gyorsítótárból való törlésére. Ez némileg hasonlít a javai szemétgyűjtőhöz. És amint emlékszel, a legjobb elmék évtizedek óta különféle módokat találtak ki a tárgyak generációnkénti megjelölésére stb.

3. probléma – különböző stratégiák . Amint azt a gyakorlat mutatja, a gyorsítótárban való tárolás és frissítés különböző stratégiái hatékonyak a különböző objektumok esetében. Egy hatékony gyorsítótárazási rendszer nem képes minden objektumra egyetlen stratégiát megvalósítani.

4. probléma – A . Nem csak objektumokat tárolhat a gyorsítótárban. Az objektumok túl gyakran tartalmaznak hivatkozásokat más objektumokra stb. Ilyen ütemben nincs szükség szemétgyűjtőre: egyszerűen nem lesz mit eltávolítani.

Ezért ahelyett, hogy magukat az objektumokat tárolnák, néha sokkal hatékonyabb a primitív mezőik értékeinek tárolása. És ezek alapján az objektumok gyors felépítésére szolgáló rendszerek.

Ennek eredményeként egy teljes virtuális DBMS-t kap a memóriában, amely gyorsan működik és kevés memóriát fogyaszt.

Adatbázis gyorsítótárazás

A gyorsítótárazáson kívül a Java programokban történő közvetlen gyorsítótárazáson kívül a gyorsítótárazást gyakran közvetlenül az adatbázisban szervezik.

Négy nagy megközelítés létezik:

Az első megközelítés az adatbázis denormalizálása . Az SQL szerver a táblákban tárolttól eltérően tárolja az adatokat a memóriában.

Amikor az adatokat táblákban tárolják a lemezen, a fejlesztők nagyon gyakran igyekeznek elkerülni az adatok többszörözését, amennyire csak lehetséges - ezt a folyamatot adatbázis-normalizálásnak nevezik. Tehát a memóriában lévő adatokkal való munka felgyorsítása érdekében fordított folyamatot hajtanak végre - az adatbázis denormalizálását. Egy rakás kapcsolódó táblázat már kombinált formában is tárolható - hatalmas táblázatok formájában stb.

A második megközelítés a lekérdezés gyorsítótárazása . És lekérdezni az eredményeket.

A DBMS úgy látja, hogy nagyon gyakran ugyanazok vagy hasonló kérések érkeznek hozzá. Ezután egyszerűen elkezdi tárolni ezeket a kéréseket és válaszaikat. Ugyanakkor gondoskodnia kell arról, hogy az adatbázisban megváltozott sorokat időben eltávolítsák a gyorsítótárból.

Ez a megközelítés nagyon hatékony lehet egy olyan embernél, aki képes elemezni a lekérdezéseket, és segít a DBMS-nek kitalálni, hogyan lehet a legjobban gyorsítótárazni őket.

A harmadik megközelítés a memórián belüli adatbázis .

Egy másik gyakran használt megközelítés. A szerver és a DBMS közé egy másik adatbázis kerül, amely minden adatát csak a memóriában tárolja. In-Memory-DB-nek is nevezik. Ha több különböző szerver éri el ugyanazt az adatbázist, akkor az In-Memory-DB használatával megszervezheti a gyorsítótárazást egy adott szerver típusa alapján.

Példa:

Megközelítés 4 - adatbázis fürt . Számos csak olvasható alap.

Egy másik megoldás a fürt használata: több azonos típusú DBMS azonos adatokat tartalmaz. Ugyanakkor az összes adatbázisból kiolvashatja az adatokat, és csak egybe írhat. Amely ezután szinkronizálva van a többi adatbázissal.

Ez egy nagyon jó megoldás, mert könnyen konfigurálható és a gyakorlatban is működik. Általában egy adatmódosítási kérelemhez 10-100 adatolvasási kérés érkezik hozzá.

A gyorsítótárazás típusai hibernált állapotban

A Hibernate három gyorsítótárazási szintet támogat:

  • Gyorsítótárazás munkamenet szinten (munkamenet)
  • Gyorsítótárazás a SessionFactory szinten
  • Gyorsítótárazási kérések (és eredményeik)

Megpróbálhatja ábrázolni ezt a rendszert egy ilyen ábra formájában:

A gyorsítótár legegyszerűbb típusa (más néven első szintű gyorsítótár ) a hibernált munkamenet szintjén valósul meg. A Hibernate alapértelmezés szerint mindig ezt a gyorsítótárat használja, és nem tiltható le .

Nézzük azonnal a következő példát:

Employee director1 = session.get(Employee.class, 4);
Employee director2 = session.get(Employee.class, 4);

assertTrue(director1 == director2);

Úgy tűnhet, hogy itt két lekérdezés fog végrehajtódni az adatbázishoz, de ez nem így van. Az adatbázishoz intézett első kérés után az Employee objektum gyorsítótárba kerül. És ha újra lekérdezi az objektumot ugyanabban a munkamenetben, a Hibernate ugyanazt a Java objektumot adja vissza.

Ugyanaz az objektum azt jelenti, hogy még az objektumhivatkozások is azonosak lesznek. Valójában ugyanaz az objektum.

A save() , update() , saveOrUpdate() , load() , get() , list() , iterate() és scroll() metódusok mindig az első szintű gyorsítótárat használják. Tulajdonképpen nincs is mit hozzáfűzni.

Második szintű gyorsítótár

Ha az első szintű gyorsítótár a munkamenet objektumhoz van kötve, akkor a második szintű gyorsítótár a munkamenet objektumhoz van kötve.SessionFactory. Ez azt jelenti, hogy az objektumok láthatósága ebben a gyorsítótárban sokkal szélesebb, mint az első szintű gyorsítótárban.

Példa:

Session session = factory.openSession();
Employee director1 = session.get(Employee.class, 4);
session.close();

Session session = factory.openSession();
Employee director2 = session.get(Employee.class, 4);
session.close();

assertTrue(director1 != director2);
assertTrue(director1.equals(director2));

Ebben a példában két lekérdezés történik az adatbázisban. A Hibernate azonos objektumokat ad vissza, de nem ugyanaz az objektum – eltérő hivatkozásokkal rendelkeznek.

A második szintű gyorsítótárazás alapértelmezés szerint le van tiltva . Ezért egy helyett két lekérdezésünk van az adatbázisban.

Az engedélyezéséhez a következő sorokat kell beírnia a hibernate.cfg.xml fájlba:

<property name="hibernate.cache.provider_class" value="net.sf.ehcache.hibernate.SingletEhCacheProvider"/>
<property name="hibernate.cache.use_second_level_cache" value="true"/>

A második szintű gyorsítótár engedélyezése után a hibernált állapot némileg megváltozik:

Session session = factory.openSession();
Employee director1 = session.get(Employee.class, 4);
session.close();

Session session = factory.openSession();
Employee director2 = session.get(Employee.class, 4);
session.close();

assertTrue(director1 == director2);

Csak mindezen manipulációk után lesz engedélyezve a második szintű gyorsítótár, és a fenti példában csak egy lekérdezés kerül végrehajtásra az adatbázisban.