2008. március 5., szerda

Architektúra part #4 – Séma objektumok (2/2)

Dimenziók (Dimensions):
A dimenziók hierarchikus (gyermek/szülő) viszonyt határoznak meg oszloppárok vagy oszlophalmazok között. Minden gyermek pontosan egy szülőhöz van társítva. Mivel a dimenzió csak logikai kapcsolatok gyűjteménye, nincs tárolási terület hozzárendelve. A dimenziót létrehozó CREATE DIMENSION parancs meghatározza a hierarchia szinteket (LEVEL), a köztük lévő viszonyt (HIERARCHY), illetve opcionálisan az ATTRIBUTE ágban kiegészítő oszlopot vagy oszlop halmazt az adott szinthez. Az oszlopok származhatnak egy táblából (denormalized) vagy több táblából (normalized). Utóbbi esetén illesztést kell alkalmazni a HIERARCHY ágban.

Szekvencia Generátor (Sequence Generator):
A szekvencia generátor segítségével számok szekvenciális sorozatát állíthatjuk elő (pl. egyedi elsődleges kulcsoknak). Segítségével többfelhasználós rendszerek esetén elkerülhetünk felesleges zárolásokat (pl. egyszerre két felhasználó is tud adatokat bevinni egy táblába). Méretük maximum 38 számjegy lehet, definíciójukat az adatszótárban (data dictionary) tároljuk. A számok generálása független az egyes tábláktól, így egy szekvencia generátort akár több táblánál is használhatunk.

Szinonimák (Synonyms):
A szinonima egy alternatív név bármely táblára, nézetre, materializált nézetre, szekvenciára, eljárásra, függvényre, csomagra, típusra, Java osztályra, felhasználó által definiált objektum-típusra vagy egy másik szinonimára. Mivel adatot a szinonima sem tárol, így számára sem szükséges területeket lefoglalni…a definícióját az adatszótárban (data dictionary) tároljuk. Használatának két fő célja a biztonság és a kényelem, valamint az, hogyha a master táblájának megváltozik a neve, akkor csak magát a szinonimát kell átírni, s utána a szinonimát használó alkalmazások probléma nélkül futnak majd. A szinonima lehet public vagy private. Előbbi minden felhasználó számára elérhető, míg utóbbi egy bizonyos felhasználó sémájában található, s mások számára a hozzáférhetőséget ő határozhatja meg.

Indexek (Indexes):
Az indexek opcionális, táblákhoz és klaszterekhez rendelhető struktúrák. Indexeket lehet egy vagy több oszlophoz rendelni, melyek segítségével egy SQL utasítás esetén gyorsabban megtalálja a keresett információt az adatbázis – ezáltal a helyesen használt indexek jelentik az I/O műveletek csökkentésének fő forrását. A következő index-sémák használhatóak: B-fa index, B-fa klaszter index, Hash klaszter index, Reverse key (inverz kulcs) index, Bitmap index, Bitmap join index. Az indexek használata automatikus, csak a létrehozásukkal és az esetleges törlésükkel kell foglalkozni. Továbbá az optimalizáló (optimizer) akár felhasználhat egy már létező indexet egy új index létrehozására, ami jóval gyorsabb index-építést eredményezhet.
Unique/Nonunique: az egyedi (unique) indexek garantálják, hogy a hivatkozott oszlopban nem szerepelhet duplikált érték. Ajánlott ezt explicit megadni mindig a CREATE UNIQUE INDEX használatával, ugyanis nem garantált, hogy egy primary key vagy unique constraint automatikusan létrehoz egy új indexet, s ha létre is hozott, arra sincs garancia, hogy az az index unique lesz.
Visible/Invisible: a láthatatlan (invisible) indexeket csak a DML műveletek kezelik, s nem használhatja őket az optimalizáló (optimizer).
Összetett indexek (Composite/Concatenated Indexes): több oszlopra definiált indexek. Az oszlopok megadásának sorrendjét nem befolyásolja az, hogy az adott oszlopok milyen sorrendben szerepelnek a táblában, azonban maga a sorrend nagyon is fontos. Célszerű a gyakran hivatkozott oszlopokat a sorrendben előre helyezni. Összetett indexekkel lényeges javulást akkor tudunk elérni, ha sikerül olyan oszlopokat találni, melyek (mind, vagy legalább nagyobb részük) gyakran szerepel(nek) egyszerre a WHERE feltételében. Maximum 32 (bitmap indexek esetén 30) oszlopot adhatunk meg.
Indexek és kulcsok (Keys): két különböző dologról van szó. Az indexek az adatbázisban tárolt, felhasználók által létrehozott struktúrák, melyek célja az adatok elérésének meggyorsítása. A kulcsok azonban szigorúan csak logikailag léteznek, s az integritás kényszerekért felelnek.
NULL értékek: különböző értékként vannak számon tartva, kivéve, hogyha az index legalább két sorában lévő nem NULL érték azonos. Tehát az UNIQUE indexekkel – mivel ott minden nem NULL érték különböző – lehet biztosítani, hogy a NULL értéket tartalmazó sorok is különbözőként legyenek kezelve (kivétel, ha minden érték NULL).
Függvény-alapú indexek (Function-Based Indexes): létrehozhatunk indexeket olyan függvényekre és kifejezésekre is, melyek tartalmaznak legalább egy oszlopot egy indexelt táblából. Ezek a függvény-alapú indexek kiszámolják a függvény vagy kifejezés értékét, s azt tárolják az indexben. Típusát tekintve B-fa vagy bitmap indexek lehetnek. A függvény maga lehet aritmetikai kifejezés, vagy olyan kifejezés, ami tartalmaz PL/SQL függvényt, csomag függvényt, C hívást vagy SQL függvényt. Nem tartalmazhat azonban aggregátum függvényeket, DETERMINISTIC-usnak kell lennie, s nem vonatkozhat LOB típusú, REF vagy beágyazott tábla oszlopára sem.
1. Használat: példák

  1. lekérdezések WHERE ágában szereplő feltételek kiszámításának gyorsítására:
    CREATE INDEX idx ON table_1 (a + b * (c - 1), a, b);
    SELECT a FROM table_1 WHERE a + b * (c - 1) <>
  2. case-insensitive keresések gyorsítása:
    CREATE INDEX uppercase_idx ON employees (UPPER(first_name));
    SELECT * FROM employees WHERE UPPER(first_name) = 'RICHARD';


2. Optimalizálás: az optimalizálónak (optimizer) szüksége van statisztikákra ahhoz, hogy használni tudja a függvény-alapú indexeket. Az optimalizáló a kifejezésfák alapján választ egy SQL utasításhoz hozza illeszkedő függvény-alapú indexet. Nyilván minél kevesebb variáció lehetséges a WHERE klóz alapján, annál hatékonyabb lesz ez a keresés.

Tárolás: az index létrehozását követően az adatbázis automatikusan lefoglal neki egy index szegmenst. A lefoglalt szegmens mérete a tábláknál már ismertetett módon történik. Azaz vagy tárolási paraméterek (storage parameteres) megadásával, vagy a PCTFREE és a PCTUSED paraméterekkel állíthatjuk be. Az index számára a létrehozásakor megadhatunk egy – az ownerjétől különböző - tablespacet is a tárolásra. Ezen túl, ha az indexet még egy külön, a tábláétól különböző diszkre is tesszük, akkor mivel az adatbázis a két diszket párhuzamosan tudja használni, teljesítménynövekedést érhetünk el.
Blokk formátuma: az index létrehozását követően az adatbázis fetcheli és rendezi az indexelt oszlopokat, s eltárolja a rowid-ket minden egyes sor index értékéhez.
Belső struktúra: az Oracle adatbázis B-fákat (ábra) használ az indexek tárolására. Ezáltal a szekvenciális keresés átlagos n/2 idejét lecsökkenti O(log(n))–re.
Unique Scan: az egyik leghatékonyabb adathozzáférési módszer. Az optimalizáló (optimizer) ezt a módszert használja unique index esetén.
Range Scan: kevésbé hatékony adathozzáférési módszer. Az adatot az index oszlopok szerinti növekvő sorrendben adja vissza, duplikált sorok esetén ROWID szerinti növekvő sorrendben.
Kulcstömörítés: lehetővé teszi, hogy az elsődleges kulcs (primary key) értékek csoportjait egy indexbe vagy egy index-szervezett táblába tömörítsük, csökkentve ezáltal az ismételt értékekből származó tárolási overheadet. Általában egy index egy csoportazonosító és egy egyedi részre bontható. A tömörítést a csoport részre végezzük: megadjuk, hogy az index milyen hosszú részét képezi, majd az ezáltal lehetséges csoportazonosítókat csak egyszer tárolunk el.

· Teljesítmény: a kulcstömörítés jelentős helymegtakarítást jelenthet, ezáltal csökkentve az I/O műveleteket és növelve a teljesítményt, azonban a kulcsok újbóli felépítése némi CPU overheadet jelenthet az indexek scanelése közben.
· Használat: az alábbi esetekben célszerű kulcstömörítést használni:

  1. nonunique reguláris indexeknél, ugyanis az Oracle adatbázis a duplikált sorokhoz duplikált keyeket használ.

  2. olyan unique indexek esetén, ahol a kulcs egyediségét nem az első attribútum generálja. Pl.: egy elemre és az elemhez történt hozzáférések időbélyegére definiáltunk indexet. Ekkor a csoport rész (prefix) lehet az elem, az egyediséget pedig (suffix rész) az időbélyeg fogja garantálni.

  3. VARRAY vagy NESTED TABLE –t tartalmazó index-szervezett tábláknál, mivel az objektumazonosító ismételt a kollekciók minden elemére.


Reverse key (inverz kulcs) indexek: a hagyományos indexekkel ellentétben megfordítják minden indexelt oszlop bájtjait (a ROWID kivételével), míg az oszlopsorrendet változatlanul hagyják. Ezáltal kizárjuk az indexen az index range scanning lekérdezéseket, de cserébe RAC-os alkalmazások futását meggyorsíthatjuk, mivel a beillesztés elosztottan mehet végbe az index levelei között.
Bitmap indexek: az Oracle adatbázis által használt B-fa indexeknél a kulcsértéket minden egyes ROWIDhez eltároljuk, így ismétlődés fordulhat elő. Bitmap indexek esetén minden kulcsértékhez egy bitmapet használunk. A bitmap minden egyes bitje egy lehetséges ROWID-t reprezentál, s akkor van beállítva, hogyha a hozzá tartozó ROWID tartalmazza a kulcsértéket.
Kevés különböző kulcsérték esetén a bitmap indexek használata (B-fa indexek helyett) jelentős helymegtakarítást jelent – alkalmazásának adattárházak (Data Warehouses) esetén van számos előnye. Lekérdezések hatékonyságának gyorsítására főként abban az esetben alkalmas, ha a WHERE feltételében ekvivalencia vizsgálatok (illetve azok AND, OR és NOT operátoros kombinációi) szerepelnek.
A legtöbb indexszel ellentétben NULL értéket tartalmazó sorokat is képes felhasználni, ami hasznos lehet a COUNT aggregátum használata esetén.
Bitmap Join indexek: több illesztett táblára is létrehozhatunk bitmap (join) indexet, ami tárolási szempontból jóval előnyösebb a materializált join nézeteknél (mivel ők nem tömörítik a hivatkozott táblák ROWID-jét).

Index-szervezett (Index-Organized) táblák:
A hagyományos táblákkal ellentétben – ahol az adatok rendezetlenül, kupacban (heap) tárolódnak -, az index-szervezett táblák adatait egy elsődleges kulcs szerint rendezett B-fában tároljuk. Ezáltal nem kell külön indexet létrehozni és fenntartani az elsődleges kulcsra (Összehasonlítás).
Előnyök:

  1. gyorsabb hozzáférés a tábla soraihoz

  2. mivel a többi, nem kulcs értékű információ is megtalálható a fában, nincs szükség további blokkhozzáférésre

  3. az elsődleges kulcs szerinti sorrendhelyes tárolás miatt minimális blokkhozzáférésre van szükség

  4. a ritkán használt nem kulcs típusú oszlopokat ki lehet pakolni egy külön kupacba, ezáltal csökkentve a B-fa méretét

  5. nem kell az elsődleges kulcsra külön indexet fenntartani (kevesebb tárhely igény)

  6. a sorrendhelyes kulcstárolás miatt kulcstömörítés alkalmazható


Overflow: mivel az index-szervezett táblákban esetlegesen nagyon sok nem kulcs típusú oszlopot is tárolhatunk, az egyes levelek mérete igencsak megnőhet, s ezáltal elveszítheti a B-fa sűrűn fürtözött tulajdonságát. Ennek elkerülése végett az OVERFLOW klózzal két részre oszthatjuk az oszlopokat: az első részbe tartoznak az index bejegyzések és fizikai ROWID-k, valamint megadhatunk néhány nem kulcs típusú oszlopot, amit szeretnénk a B-fában tartani. A második részbe (overflow rész) kerül a többi nem kulcs típusú oszlop, melyeket külön tárolunk.
Másodlagos indexek: index-szervezett tábláknál is van lehetőség nem kulcs típusú oszlopokra indexeket létrehozni (ún. másodlagos/secondary indexek). Ezek működése azonban általában lassabb a hagyományos táblákra létrehozott indexekénél (azonos működés érhető el, ha helyes sejtésünk van az adat fizikai elhelyezkedéséről).
UROWID: az index-szervezett táblák sorainak azonosítására használható, logikai elsődleges kulcs alapú ROWID-k.
Alkalmazások: az elsődleges kulcs alapú lekérdezéseket használó, valamint a tárhellyel takarékoskodni akaró alkalmazások számára ideális. Pl.: OLTP (Online Transaction Processing), Internet (kereső motorok és portálok), Elektronikus kereskedelem, Adattárházak (Data Warehouses), Analitikus függvények.

Alkalmazás Domain Indexek (Application Domain Indexes):
Az Oracle adatbázis indexelése kiterjeszthető komplex adattípusokra - mint pl. dokumentumok, spatial adatok, képek, videók, stb. – is. Ezeket az indexeket hívjuk domain indexeknek, melyeket a Cartridge szoftverrel lehet szabályozni.

Klaszterek (Clusters):
Klaszternek nevezzük táblák egy csoportját, melyek – mivel közös oszlopokat használnak – ugyanazon az adatblokkokon osztoznak (példa).
Előnyei:

  1. kevesebb I/O művelet az egy klaszteren belül lévő illesztett táblákra

  2. gyorsabb hozzáférés az egy klaszteren belül lévő illesztett táblákra

  3. klaszter kulcsértékek (és indexek) csak egyszer tárolódnak, ezáltal kevesebb tárhelyet fogyasztanak.


Hash klaszterek (Hash Clusters):
A hash klaszterek bizonyos értelemben megfelelnek a klaszterekre definiált hagyományos indexekkel, azzal a különbséggel, hogy a kulcs hash értékét tárolják. Jobb teljesítményt lehet velük elérni olyan tábláknál, melyen gyakran alkalmaznak ekvivalencia vizsgálatos feltételt tartalmazó lekérdezéseket, mivel a hash kulcs közvetlenül a diszken lévő adatra mutat.


Kapcsolódó Link
Oracle® Database Concepts – Schema Objects

1 megjegyzés:

hobs írta...

formázom a html kódot, ha hazaértem, mert ez a külső formázó bizony eléggé gányol és...