Adatvezérelt rendszerek
Lekérdezés optimalizálás célja
- időre optimalizálunk
- Válaszidő befolyásoló tényezői
- I/O költség
- ez a legmeghatározóbb
- Moore törvény nem igaz
- CPU használat
- komplex lekérdezéseknél, összetett számításoknál
- Memória használat → Cache hatása miatt
- adatbázis végzi az optimalizálást
- statisztikák alapján
- költség becslés = válaszidő (CPU + I/O idő)
- triviális terv → ezeket NEM kell optimalizálni, mert az több idő lenne
- egyszerűbb lekérdezéshez egyértelműen generálható
- szabály alapú lekérdezési tervek
- ha nem készíthető triviális terv
- összetett optimalizálás
- fázis
- egyszerű szabály alapú átalakítások (hash join-t preferál)
- ha így már adott költség alatti, akkor végrehajtja
- fázis
- kibővített átalakítások
- ha így már adott költség alatti, akkor végrehajtja
- fázis → párhuzamos végrehajtás vizsgálata
- lekérdezés feldolgozás menete
- elemző (parser) → optimalizáló → sorfordító → végrehajtó
- elemző: szövegből logikai tervet készít (lekérdezés fordítása)
- optimalizáló: fizikai terv készítése, táblák bejárása és összekapcsolása
- sorfordító: I/O műveletekre leképzi
- végrehajtó: végrehajtja
- logikai végrehajtási terv
- elemző fa
- relációk (levél elemek)
- műveletek (csomópontok) pl join, szűrés
- descartes-szorzat, projekció, szelekció, összekapcsolás, ismétlődés szűrése, csoportosítás, rendezés
- adatok lentről fölfele "áramlanak"
- elemző fa átalakítása
- cél: optimális logikai terv kialakítása, fizikai végrehajtási terv keresési terének vágása
- alapkoncepciók:
- kiválasztás műveletek lefele mozgatása (szűrés lefele, hogy kevesebb adattal kelljen dolgozni!)
- join operátorok használata (direkt szorzatot kerüljük)
- join operátorok egyik attribútuma mindig tábla
- kiválasztások leírása a diasorban!
- fizikai végrehajtási terv
- algoritmusok konkretizálása
- tervek szabály alapján vagy költségbecslés alapján
- join algoritmusok:
- nested loop join → egymásba ágyazott kettős for ciklus
- I/O költség → O(blokk_szám_1 * blokk_szám_2)
- tetszőleges méretű táblák esetén működik
- hash join
- kisebb reláció beolvasása
- vödrös hash építése a memóriában (kulcs a join operátorban szereplő oszlop)
- a nagyobbik reláció beolvasása, kapcsolódó rekordok keresése a vödrös hashben
- I/O költség → O(blokk_szám_1 + blokk_szám_2)
- negatívumok: el kell férnie a táblának a memóriában, csak egyenlőség alapon lehet keresni
- sort merge join
- mindkét reláció beolvasása a memóriába, majd rendezzük kulcs szerint
- összefésüljük a 2 listát
- kis méretű relációk esetén jó, index kell a rendezés miatt
- I/O költség → O(blokk_szám_1 + blokk_szám_2)
- tábla elérési módok
- 2 kategória:
- teljes átvizsgálás → mindet felolvassuk a disk-ről (kis táblák esetén, ha minden rekordra szükség van)
- index alapú átvizsgálás → szűrés esetén, rendezés megvalósításakor
- table scan → ha nincs semmilyen index, szűrési feltételt is kiértékeli
- clustered index scan → nyalábolt adatolvasás
- adatblokkok index szerint rendezve (primary key mentén jön létre automatikusan MSSQL-ben)
- table scan helyett ezt preferálja!
- nonclustered index scan → =-ség jellegű kiértékelésekkor
- clustered/nonclustered index seek
- index scan-hez hasonló
- B*fa leveleinek bejárása kezdőemetől
- kisebb, nagyobb, between kiértékelésére
- covered index
- B*fa levelének bővítése oszlopokkal, nem kell kiolvasni a tényleges rekordot
- indexek
- egyszerű, összetett, clustered (memórián is olyan sordban van, csak 1clustered index lehet)
- clustered és nonclustered index együtt → nonclustered mutat a clustered-re és az meg a disk-re
- nézetek is indexelhetőek MSSQL-ben
- lekérdezési tervek cach-e → plan cache
- ha ugyanolyan struktúrájú lekérdezés jön, és ha statisztikák nem változtak
- tárolt eljárásra előre vannak elkészített lekérdezési tervek
- itt megadhatjuk, hogy mire optimalizáljunk
- általános tanácsok
- statisztikák legyenek naprakészek (ne kapcsoljuk őket ki!)
- lekérdezés struktúrája
- gondolkodjuk az adatbázis fejébel
- többféleképp megfogalmazható dolgoknál
- minél egyszerűbben írjuk le, annál jobb!
- select * -ot kerüljük! (nem tudja kihasználni az indexelést)
- inkább join mint in / not in, exists / not exist
- exists helyett inkább in
- nézeteket kerüljük ha lehet
- kerüljük a vagy feltételeket → union all
- kerüljük az al-lekérdezéseket
- indexek
- sématervezéskor már gondoljunk erre!
- összetett indexnél a hierarchia számít
- matematikai műveleteket kerüljük, mert elronthatja az indexelést (price+10<100 helyett price<90 legyen)
- függvények használata
- select listában lehet
- where feltételben ne használjuk!
- MongoDB
- indexelés meghatározó (csak keresési célt szolgál, mivel nincs join)
- index típusok
- egyszerű & összetett
- unique index
- tömbök tartalmát is indexeli
- beágyazott dokumentumokat is indexeli
- indexet _id-n kívül létre kell hozni
- nem használ statisztokákat
- mindet elkezdi lehajtani, amelyik első 101db-ot visszaadja → azt fogja használni
- optimalizáló lépések
- szűrés előre mozgatás
- sklp és limit előre mozgatás (projekció elé)
- összevonás (limit+limit, skip+skip)
- van terv cache
- csak a struktúrája szerepel, hogy mire szűrtünk azt pl nem (csak a mezők neve, az érték nem)
- query.explain() → megmutatja a tervét