Ruby on Rails-ohjelmiston kehittäminen. Indeksit v2
Damian Watroba
Software Engineer
Kun työskentelemme Ruby on Rails-kehyksen kanssa, käsittelemme yleensä relaatiotietokantoja, kuten MySQL:ää tai PostgreSQL:ää. Määritellessämme migraatioita Active Record Migrations -ohjelman avulla törmäämme niin sanottuihin indekseihin, mutta aloittelijat eivät useinkaan oikein ymmärrä indeksejä ja niiden tuomia etuja.
Kun työskentelemme Ruby on Rails-kehyksen kanssa, käsittelemme yleensä relaatiotietokantoja, kuten MySQL:ää tai PostgreSQL:ää. Määritellessämme migraatioita Active Record Migrations -ohjelman avulla törmäämme niin sanottuihin indekseihin, mutta aloittelijat eivät useinkaan oikein ymmärrä indeksejä ja niiden tuomia etuja.
Tässä postauksessa selitän, mitä indeksit ovat, mihin niitä käytetään ja esittelen joitakin hyviä käytäntöjä niiden käyttämiseen.
Tietokanta
Tietokantamoottoreita on monia, ja yksi suosituimmista on aiemmin mainitut MySQL, PostgreSQL, Oracle tai Microsoft SQL Server. Ne ovat kaikki relaatiotietokantoja, mikä tarkoittaa, että kaikki tiedot liittyvät toisiinsa ja ne tallennetaan taulukoihin. Jokaista taulukon riviä kutsutaan tietueeksi, ja jokaisella on oma yksilöllinen tunnisteensa (id). Voit tarkistaa suosituimpien tietokantamoottoreiden paremmuusjärjestyksen osoitteessa https://db-engines.com/en/ranking. Sieltä löydät myös joitakin ei-relationaalisia tietokantoja, kuten MongoDB.
Indeksin luominen
Tietokantojemme taulukoissa voi olla muutamasta muutamaan kymmeneen - ääritapauksissa jopa useisiin satoihin - sarakkeisiin. Muista, että kussakin taulussa voi olla rajoittamaton määrä rivejä. Tämä määrä ei johdu suoraan tietokannan rakenteesta, ja meidän on aina oletettava, että tietueiden määrä kasvaa vähitellen ja sen seurauksena tietokantamme kasvaa. Alkuperäiset oletukset ja nykyisissä sovelluksissa kirjoitetut kyselyt voivat olla hyviä pienelle tai keskisuurelle tietueiden määrälle, mutta ajan mittaan, kun tietoja tulee lisää, sovelluksen kommunikointi tietokannan kanssa lakkaa olemasta tehokasta.
Ohjelmoijan tehtävänä on kirjoittaa kyselyitä, joilla haetaan tietoja taulukosta tai taulukoista, mutta kyselyjen optimaalinen käsittelytapa riippuu tietokantamoottorista. Muista, että tietokantamoottorit lataavat tiedot levyltä muistiin ja skannaavat ne sitten. Tämä tarkoittaa sitä, että jos monet käyttäjät suorittavat monimutkaisia operaatioita samanaikaisesti, useat heistä joutuvat odottamaan vuoroaan, koska hakujen toteuttamiseen ei ole riittävästi resursseja. Siksi asiaankuuluvat indeksit ovat niin tärkeitä.
Wiki: Indeksi - tietorakenne, joka nopeuttaa hakutoimintojen suorittamista taulukossa.
Kullekin indeksille on määriteltävä avaimet (yhdelle tai useammalle sarakkeelle), joita käytetään tietueiden etsimiseen taulukosta. Indeksissä olevat tiedot lajitellaan aiemmin määritellyn avaimen mukaan, mikä nopeuttaa huomattavasti tietojen etsimistä taulukosta. Yksinkertaisin esimerkki jokapäiväisestä elämästä on puhelinluettelo, jossa ihmiset lajitellaan etu- ja sukunimen mukaan. Voidaan sanoa, että indeksimme on tässä tapauksessa etu- ja sukunimi.
Miten valitset parhaan indeksiavaimen? Se ei ole vaikeaa - muista vain muutama sääntö. Luo indeksi, joka perustuu sarakkeisiin, jotka:
- käytetään usein kyselyissämme (WHERE),
- yhdessä toistensa kanssa antavat ainutlaatuisen arvon (eli arvon, joka osoittaa täsmälleen yhden rivin),
- käytetään niin sanottuina yhdistävinä sarakkeina (JOIN),
- antaa valikoivimmat avaimet, eli ne, jotka tuottavat vähiten rivejä kyselyä kirjoitettaessa.
Jos tiedämme jo, mitkä avaimet ovat optimaalisia taulullemme, voimme myös kysyä itseltämme, kuinka monta indeksiä tarvitsemme. Tässä tapauksessa on parasta tietää jo suunnitteluvaiheessa, mitkä kyselyt tulevat viittaamaan taulukkoon.
Luodaan indeksit tietyille kyselyille, jotka tulevat näkyviin, mutta ei kirjoiteta niitä jokaiselle sarakkeelle. Indeksit, kuten taulukotkin, on tallennettava jonnekin, joten kun luomme taulukoita, joissa on indeksi jokaiselle sarakkeelle, meidän on otettava huomioon, että käytetyn tilan määrä voi kasvaa huomattavasti.
Luo uniikki indeksi
Toinen asia, jota meidän on pohdittava, on ainutlaatuisuus. Kannattaa käyttää ylimääräiset viisi minuuttia sen miettimiseen, onko indeksimme todella ainutlaatuinen. Näin kerromme kyselyn optimoijalle, ettei sen tarvitse odottaa kaksoiskappaleita kyselyssä. Esimerkiksi sähköpostiosoitteet:
frozenstringliteral: true
class CreateUsers < ActiveRecord::Migration[6.0]
def change
createtable :users do |t|
t.string :email, null: false
end
addindex :users, :email, unique: true
end
end
PostgreSQL-moottorin esimerkissä näytän eron kyselynopeudessa sähköpostisarakkeessa, jossa on yksilöllinen indeksi ja ilman indeksiä.
1. Voit käyttää näytettä koodi pätkiä omassa tietokannassasi, jotta voit testata alla olevaa esimerkkiä. Luodaan ensin tyhjä taulukko, jossa on yksi sarake:
CREATE TABLE users (
email varchar
);
2. Luodaan 10 000 tietuetta testiä varten:
DO $
BEGIN FOR i IN 1..10000 LOOP
INSERT INTO users values((select 'user' || i || '@example.com'));
END LOOP; END;
$;
Käytämme EXPLAIN ANALYZE -ohjelmaa tarkistaaksemme, kuinka nopeasti kyselymme käsitellään, kun haluamme löytää tietyn käyttäjän tietokannasta.
EXPLAIN ANALYZE SELECT email FROM users WHERE email = 'user890example.com';
Kyselymme pakotti iteroimaan koko taulukon ympäri etsiessään meitä kiinnostavaa tietuetta.
Tätä prosessia kutsutaan peräkkäiseksi skannaukseksi. Tässä tapauksessa koko taulukon lukeminen ja tiettyjen rivien suodattaminen pois on paras tapa tehdä työ.
PostgreSQL suodattaa tarpeettomat rivit pois ja palauttaa vain ne, jotka kiinnostavat meitä. Tämä on todella paras tapa toimia tässä tapauksessa. Peräkkäinen skannaus ei ole aina huono asia, vaan on tapauksia, joissa peräkkäinen skannaus on ihanteellinen.
4. Nyt on aika tarkistaa kysely, joka on jo tehty taulukkoon, jossa on INDEX UNIQUE. Asetetaan indeksi ja suoritetaan kysely.
EATE UNIQUE INDEX index_email on users(email);
EXPLAIN ANALYZE SELECT email FROM users WHERE email = 'user890example.com';
Tällä kertaa PostgreSQL hyödynsi indeksin skannausta, koska kaikki tarvittavat sarakkeet ovat jo indeksissä.
Vain muutaman rivin valitseminen on erittäin tehokasta, kun käytät indeksiä. Jos kuitenkin valitaan enemmän tietoja, indeksin ja taulukon skannaaminen on liian aikaa vievää.
Yhteenveto
Kuten näet, indeksillä varustettua saraketta koskevan kyselyn suoritusaika on paljon lyhyempi (näytetyssä esimerkissä se laskee 1,267 ms:stä 0,111 ms:ään, eli peräti 91,24%!). Tärkein ero on PostgreSQL:n tapa etsiä meitä kiinnostavaa tietuetta. Ensimmäisessä tapauksessa tietokantamoottorin oli etsittävä koko taulusta tarvitsemamme tietue. Toisessa tapauksessa indeksirakenne on kuitenkin lajiteltu ja yksilöllinen, joten moottori tiesi, missä tietue sijaitsi, mikä nopeutti huomattavasti kyselyn käsittelyaikaa.
Kun kyseessä ovat suuret tietokannat ja hyvin monimutkaiset kyselyt, oikein asetetut indeksit voivat nopeuttaa sovelluksesi työtä merkittävästi ilman, että sinun tarvitsee lisätä sen koneen nopeutta, jolla teet tietokantahakuja.
On syytä muistaa, että indeksien luominen jokaiselle sarakkeelle ei ole hyvä käytäntö. Luodut indeksit nopeuttavat optimoijan työtä, kun etsitään kiinnostavaa tietoa, mutta samalla hidastavat uusien lisäämistä ja olemassa olevien päivittämistä.