• Nem Talált Eredményt

9. Lecke: Indexelés, kapcsolatok, táblatulajdonságok

9.5 Indexelés

Ahogyan azt korábban megjegyeztük, a táblák rekordjai háttértárakon tá-rolódnak. Amikor a felhasználó meg szeretne nézni néhány rekordot, a DBMS-nek a lemezről kell beolvasnia az adatokat, majd relációvá alakítva el kell külde-nie a felhasználó kliensprogramjához. A lemezműveletek mindig kritikus pon-tot jelentenek a sebesség tekintetében. Amikor egy tábla valamelyik mezőjé-nek értékétől függően akarjuk a rekordok egy részét kiválogatni, ez a probléma hatványozottan jelentkezik. A DBMS ugyanis úgy állítja össze a rekordok szük-séges részhalmazát, hogy minden rekordot beolvas, és a kérdéses mező

rekor-donkénti vizsgálata alapján eldönteni, hogy mely rekordok kerüljenek az eredményhalmazba. Előfordulhat, csak a legutolsó rekord, vagy egyetlen egyed sem elégíti ki a feltételt, de ennek eldöntéséhez mindig minden rekordot meg kell vizsgálni.

Az indexelés jelentősen redukálja az ilyen műveletek lebonyolításához szükséges időt.

A technika lényege, hogy a bázistábla (a rekordok adatait tároló reláció) létrehozásakor bármelyik mezőt indexelhetjük. Az indexelés azt jelenti, hogy a DBMS úgynevezett indextáblát (röviden indexet) hoz létre a mező számára. A bázistábla feltöltésekor az indexelt mező összes előforduló értékét bemásolja az indextáblába, és az index rekordjait sorba rendezi az értékek szerint. Az indextáblában a minden mezőérték mellett följegyzi azt is, hogy a bázistábla adott értéket tároló rekordja hol található a lemezen.

Az indextábla minden sora az indexelt mező egye-egy értékét és a hozzá tartozó rekordmutatót tárolja. A sorok az indexelt értékek sze-rint rendezettek.

Ha a bázistáblában egy indexelt mező alapján akarunk rekordokat keresni, vagy kiválogatni, akkor a DBMS automatikusan beolvassa a memóriába a teljes indextáblát, kiválogatja a megfelelő mezőértékeket (ez a művelet a rendezett-ség miatt gyors lesz), és bázistáblának csak a kiválasztott, az ezeket az értékeket tartalmazó rekordjait olvassa be a lemezről.

Egy táblában bármennyi mező indexelhető. Ha több mezőt is indexelünk, akkor természetesen mindegyik számára különálló indextábla készül.

A fentiek alapján könnyen következtethetünk arra, hogy érdemes minden mezőt indexelni. Ez nem pontosan így van, ugyanis az indexelésnek negatívumai is vannak. Minden indextábla helyet foglal a lemezen, és ezzel növeli az adat-bázis méretét. Ráadásul az indexek csak akkor működnek helyesen, ha a DBMS a bázistábla rekordjainak változásakor (új rekord, rekordtörlés, mezőérték vál-toztatás) automatikusan frissíti az indextáblát is. Ha például új rekord kerül a bázistáblába, akkor be kell tölteni az indexet, beszúrni a bázistábla az új mező-értékét, majd újrarendezni és lemezre másolni az indextáblát. Ez mindig időt vesz igénybe, azért az indexelés némileg lassítja a rekordkezelő műveleteket.

Ha helyesen akarunk eljárni, akkor csak azokat a mezőket indexeljük,

 amelyek alapján gyakran válogatunk ki rekordokat egy nagyméretű bá-zistáblából, vagy

 biztosítani akarjuk, hogy a mező rekordonként egyedi értéket tartal-mazzon, azaz alternáló kulcs legyen, vagy

 a mezőt idegen kulcsként akarjuk használni.

9.5.1 Indexelés típusai

Indexet létrehozhatunk egy vagy több mező értékeinek kombinációja alap-ján. Az indexelés lehet egyedi, és nem egyedi.

Az egyedi index használata gyorsabb, de csak olyan mezők esetében lehet-séges, amelyek egyes értékei a bázistábla egy-egy rekordjában fordulnak csak elő, nem ismétlőnek, azaz valójában kulcsjelöltek.

Pontosan ezért az egyedi indexelésű mezőkben a DBMS nem engedi meg az mezőértékek ismétlődését. Az ilyen indexelést nem csak a kereséséi sebes-ség növelésére, hanem egy mező egyedi értékeinek biztosítására is használjuk.

9.5.2 Indexelés beállítása

Nem egyedi indexelés

A nem egyedi indexelés a meződefiníciók után, azoktól vesszővel elválaszt-va az alábbi formában adható meg:

INDEX [index_név] [index_típus] (indexelt_mező,...) [index_opciók]

Az könnyebb megértés kedvéért lássunk egy egyszerű példát, amely az összes választható opciót elhagyva állítja be a nagyker tábla nKapcsolat mezőjének nem egyedi indexelését. Abból in-dulunk ki, hogy gyakran keressük a nagykereskedések rekordjait a kapcsolattartó neve alapján, de feltételezzük, hogy a különböző nagykerek munkatársainak lehet azonos a nevük.

CREATE TABLE nagyker (

idNagyker int(10) UNSIGNED NOT NULL

PRIMARY KEY AUTO_INCREMENT, nCegNev varchar(50) DEFAULT NULL,

nKapcsolat varchar(30) DEFAULT NULL, nTelefon varchar(30) DEFAULT NULL, INDEX idx1 (nKapcsolat)

)ENGINE=InnoDB DEFAULT CHARSET=utf8;

A példában csak az index_név, és az indexelt_mező opciókat használtuk ezért röviden most tekintsük át az összes lehetőség jelentését!

index_név: Példánkban ’idx1’, az index neve. Ez tábla szinten egyedi karaktersorozat, amivel az indexet azonosíthatjuk, illetve hivatkozha-tunk rá. Az index későbbi törlésekor, vagy módosításkor lehet rá szük-ség, ezért bár nem kötelező, célszerű megadni.

index_típus: A kétféle indexelési típus a b-fa (BTREE) és a hashing (HASH) között választhatunk. A HASH csak a MEMORY és az NDB tábla-motorok esetében használható, az InnoDB, és a többi motor mindig b-fa típusú indexet készít.

indexelt_mező: Példánkban egyedül az indexelt mezőt adtuk meg. A zá-rójelek között egyszerű index esetén egy, összetett indexelés esetén több, vesszővel elválasztott mezőnevet sorolunk fel.

index_opciók: az indexelés további, finomhangolására használható op-ciói.

Egyedi indexelés:

Az egyedi indexelés szintén a meződefiníciók után, vesszővel elválasztott, úgynevezett megszorítás definícióval adató meg:

[CONSTRAINT [szimb_név]] UNIQUE [INDEX|KEY]

[index_név] [index_típus] (indexelt_mező,...) [index_opciók] ...

A megszorítások mindegyike a CONSTRAINT kulcsszóval kezdődik, amit egy adatbázis szintjén egyedi, úgynevezett szimbolikus név követ. Szükség ese-tén ezzel a névvel azonosítható a megszorítás. Az ezt követő UNIQUE kulcsszó jelzi, hogy egyedi indexet szeretnénk készíteni. Az INDEX|KEY kulcsszavak kompatibilitási okokból maradtak a nyelvben. Egymás szinonimái, de el is hagy-hatók. Minden ezt követő opció jelentése megegyezik a nem egyedi indexelés-nél leírtakkal.

Tegyük fel, hogy webes kereskedésünk adatbázisában egyedi inde-xeléssel szeretnénk biztosítani, hogy ne lehessen kétszer szerepel-tetni ugyanazt a cégnevet. Az alábbi példában úgy módosítanunk a tábla modelljét, hogy az nNEv mező értékei egyedi indexelésűek

nKapcsolat varchar(30) DEFAULT NULL, nTelefon varchar(30) DEFAULT NULL, INDEX idx1 (nKapcsolat),

CONSTRAINT szimNagykIdx UNIQUE idx2 (nCegNev) )ENGINE=InnoDB DEFAULT CHARSET=utf8;