Indeksit
Indeksi on tietokannan taulun yhteyteen tallennettu hakemistorakenne, jonka tavoitteena on tehostaa tauluun liittyvien kyselyiden suorittamista. Indeksin avulla tietokantajärjestelmä voi selvittää tehokkaasti, missä päin taulua on rivejä, jotka täsmäävät tiettyyn hakuehtoon.
Indeksiä voi ajatella samalla tavalla kuin kirjan lopussa olevaa hakemistoa, jossa kerrotaan hakusanoista, millä kirjan sivuilla ne esiintyvät. Hakemiston avulla löydämme tietyn sanan sijainnit paljon nopeammin kuin lukemalla koko kirjan läpi.
Pääavaimen indeksi
Kun tietokantaan luodaan taulu, sen pääavain saa automaattisesti indeksin. Tämän seurauksena voimme suorittaa tehokkaasti hakuja, joissa ehto liittyy pääavaimeen.
Esimerkiksi kun luomme SQLitessä taulun
CREATE TABLE Tuotteet (id INTEGER PRIMARY KEY, nimi TEXT, hinta INTEGER);
niin taululle luodaan indeksi sarakkeelle id
ja voimme etsiä tehokkaasti tuotteita id-numeron perusteella.
Tämän ansiosta esimerkiksi seuraava kysely toimii tehokkaasti:
SELECT hinta FROM Tuotteet WHERE id=3;
Voimme varmistaa tämän kysymällä kyselyn suunnitelman:
sqlite> EXPLAIN QUERY PLAN SELECT hinta FROM Tuotteet WHERE id=3;
selectid order from detail
---------- ---------- ---------- ---------------------------------------------------------
0 0 0 SEARCH TABLE Tuotteet USING INTEGER PRIMARY KEY (rowid=?)
Suunnitelmassa näkyy SEARCH TABLE
,
mikä tarkoittaa, että kysely pystyy hakemaan
taulusta tietoa tehokkaasti indeksin avulla.
Indeksin luominen
Pääavaimen indeksi on kätevä,
mutta voimme haluta myös etsiä tietoa
jonkin muun sarakkeen perusteella.
Esimerkiksi seuraava kysely hakee rivit
sarakkeen hinta
perusteella:
SELECT nimi FROM Tuotteet WHERE hinta=4;
Tämä kysely ei ole oletuksena tehokas,
koska sarakkeelle hinta
ei ole indeksiä.
Näemme tämän pyytämällä taas selitystä kyselystä:
sqlite> EXPLAIN QUERY PLAN SELECT nimi FROM Tuotteet WHERE hinta=4;
selectid order from detail
---------- ---------- ---------- -------------------
0 0 0 SCAN TABLE Tuotteet
Nyt suunnitelmassa näkyy SCAN TABLE
,
mikä tarkoittaa, että kysely joutuu käymään läpi
taulun kaikki rivit.
Tämä on hidasta, jos taulussa on paljon rivejä.
Voimme kuitenkin luoda uuden indeksin,
joka tehostaa saraketta hinta
käyttäviä kyselyitä.
Saamme luotua indeksin komennolla CREATE INDEX
näin:
CREATE INDEX idx_hinta ON Tuotteet (hinta);
Tässä idx_hinta
on indeksin nimi, jolla voimme viitata siihen myöhemmin.
Indeksi toimii luonnin jälkeen täysin automaattisesti,
eli tietokantajärjestelmä osaa käyttää sitä kyselyissä
ja huolehtii sen päivittämisestä.
Indeksin luomisen jälkeen voimme kysyä uudestaan kyselyn suunnitelmaa:
sqlite> EXPLAIN QUERY PLAN SELECT nimi FROM Tuotteet WHERE hinta=4;
selectid order from detail
---------- ---------- ---------- -----------------------------------------------------
0 0 0 SEARCH TABLE Tuotteet USING INDEX idx_hinta (hinta=?)
Indeksin ansiosta suunnitelmassa
ei lue enää SCAN TABLE
vaan SEARCH TABLE
.
Suunnitelmassa näkyy myös,
että aikomuksena on hyödyntää indeksiä idx_hinta
.
Lisää käyttötapoja
Voimme käyttää indeksiä myös kyselyissä,
joissa haemme pienempiä tai suurempia arvoja.
Esimerkiksi sarakkeelle hinta
luodun indeksin
avulla voimme etsiä vaikkapa rivejä,
joille pätee ehto hinta<3
tai hinta>=8
.
Indeksi on myös mahdollista luoda usean sarakkeen perusteella. Esimerkiksi voisimme luoda indeksin näin:
CREATE INDEX idx_hinta ON Tuotteet (hinta,nimi);
Tässä indeksissä rivit on järjestetty ensisijaisesti hinnan ja toissijaisesti nimen mukaan. Indeksi tehostaa hakuja, joissa hakuperusteena on joko pelkkä hinta tai yhdessä hinta ja nimi. Kuitenkaan indeksi ei tehosta hakuja, joissa hakuperusteena on pelkkä nimi.
Milloin luoda indeksi?
Periaatteessa voisi ajatella, että taulun jokaiselle sarakkeelle kannattaa luoda indeksi, jolloin monenlaiset kyselyt ovat nopeita. Tämä ei ole kuitenkaan käytännössä hyvä idea.
Vaikka indeksit tehostavat kyselyitä, niissä on myös kaksi ongelmaa: indeksin hakemistorakenne vie tilaa ja indeksi myös hidastaa tiedon lisäämistä ja muuttamista. Jälkimmäinen johtuu siitä, että kun taulun sisältö muuttuu, niin muutos täytyy myös päivittää kaikkiin tauluun liittyviin indekseihin. Indeksiä ei siis kannata luoda huvin vuoksi.
Hyvä syy indeksin luontiin on, että haluamme suorittaa usein tietynlaisia kyselyitä ja ne toimivat hitaasti, koska tietokantajärjestelmä joutuu käymään läpi turhaan jonkin taulun kaikki rivit kyselyn aikana. Tällöin voimme lisätä taululle indeksin, jonka avulla tällaiset kyselyt toimivat jatkossa tehokkaasti.
Indekseillä on käytännössä suuri vaikutus tietokantojen tehokkuuteen. Moni tietokanta toimii hitaasti sen takia, että siitä puuttuu oleellisia indeksejä.