Databaseindekser bruges til at fremskynde forskellige tabeloperationer. Men før du opretter et indeks, er det vigtigt at vide, om du virkelig har brug for et indeks? Og hvis du skal lave et indeks, hvad er de vigtige punkter, du skal huske på? Det er her, databaseindeksdesign kommer ind i billedet.
Denne artikel har til formål at besvare disse spørgsmål om databaseindeksdesign og kaste lys over nogle af de vigtigste overvejelser, som en databaseudvikler bør tage i betragtning, når de designer et indeks.
1. Tabelstørrelse
Det første spørgsmål, som en databaseudvikler skal stille, før du opretter et indeks, er, om tabellen er stor nok til effektivt at bruge indekser. Hvis tabelstørrelsen er lille, kan SQL Server-motoren scanne hele tabellen hurtigere end at søge i tabellen gennem et indeks. Indekser i sådanne tilfælde har ingen nytte og skaber en overhead, mens de udfører databaseoperationer.
2. Kolonnetyper
Indekser skal oprettes på en primær nøglekolonne eller enhver kolonne, der indeholder unikke værdier, og som har en NOT NULL-begrænsning. Desuden er det tilrådeligt at oprette indekser på numeriske kolonner, da numeriske kolonner har tendens til at have mere unikke værdier sammenlignet med ikke-numeriske kolonner. Dårligt databaseindeksdesign bruger indekser på kolonner, der har meget få unikke poster og kan resultere i meget tidskrævende forespørgsler.
Overvej en tabel med navnet Patienter, som indeholder hundredtusindvis af journaler. Patienttabellen ville indeholde en kolonne kaldet "Køn", som kun kan have to unikke værdier "Mand" og "Kvinde". Hvis du opretter et indeks på "Kønskolonnen", vil posterne blive sorteret i stigende eller faldende alfabetisk rækkefølge.
Så hvis du har en million poster i Patienttabellen, og antallet af mandlige og kvindelige patienter er lige store, vil den første halve million poster i indekset have køn "Kvinde", og den anden halve million vil have køn "Mand". Hvis du nu vil søge efter en hun, der findes i rækken 490.000 af kvindelige poster, skal SQL Server Engine scanne gennem 490.000 poster. På den anden side kan søgningen med unikke numeriske værdier være ekstremt hurtig, da SQL Server-indekser gemmes i form af B + træer, og så numeriske værdier i træknuderne kan fremskynde databaseoperationer.
3. Antal indekser
Officielt kan du oprette et klynget indeks og så mange ikke-klyngede indekser, som du vil, for hver databasetabel. Det er dog et godt databaseindeksdesign at oprette ét klynget indeks og kun et begrænset antal absolut nødvendige ikke-klyngede indekser. Oprettelse af for mange ikke-klyngede indekser kan faktisk sænke opdaterings- og indsæt-operationer, fordi når en post opdateres eller indsættes, og en kolonneværdi ændres, skal alle de tilknyttede indekser opdateres.
Overvej et scenario, hvor vi har to ikke-klyngede indekser, det første indeks sorterer posterne efter alder, og det andet indeks sorterer posterne efter både køn og alder.
Her er det første indeks:
Alder | Registrer adresse |
10 | Optag adresse |
22 | Optag adresse |
29 | Optag adresse |
32 | Optag adresse |
33 | Optag adresse |
36 | Optag adresse |
40 | Optag adresse |
49 | Optag adresse |
54 | Optag adresse |
59 | Optag adresse |
Og her er den anden:
Køn | Alder | Record-adresse |
Kvinde | 10 | Optag adresse |
Kvinde | 29 | Optag adresse |
Kvinde | 33 | Optag adresse |
Kvinde | 40 | Optag adresse |
Kvinde | 54 | Optag adresse |
Mand | 22 | Optag adresse |
Mand | 32 | Optag adresse |
Mand | 36 | Optag adresse |
Mand | 49 | Optag adresse |
Mand | 59 | Optag adresse |
Hvis en post med en alder af 40 af en eller anden grund skal opdateres til en alder af 15, så skal det første indeks opdateres for at flytte posten fra den 7. position(40) til den anden position for at holde indekset sorteret. På samme måde i det andet indeks vil posten i 4. indeks blive flyttet til det andet indeks. En masse omrokering skal finde sted. Derfor er det klogt at holde antallet af indekser på et minimum for de kolonner, der løbende opdateres, når man tænker på databaseindeksdesign. En kolonne bør heller ikke bruges i flere ikke-klyngede indekser.
4. Lagerplacering af indekser
Lagerplaceringen af et indeks kan påvirke ydeevnen af de forespørgsler, der bruger indekset, og er derfor også en del af et godt databaseindeksdesign. Som standard gemmes et klynget indeks i den samme filgruppe som den tabel, hvor indekset er oprettet. For ikke-klyngede indekser kan indekset gemmes i den samme filgruppe eller i forskellige filgrupper, der spænder over flere diskdrev. Forespørgselsydeevnen for ikke-klyngede indekser kan forbedres væsentligt ved at gemme ikke-klyngede indekser på flere diskdrev. Dette skyldes, at input/output-ydeevnen af forespørgslen vil blive forbedret som følge af, at dataene distribueres på forskellige områder af drevet.
Standardlagerpladsen for indekser kan også ændres ved at angive en værdi for FILLFACTOR-indstillingen. Da indekser fysisk lagres i form af B+ træer, gemmes indeksdataene på bladsider. Med FILLFACTOR-indstillingen kan du indstille procentdelen af siderne på bladniveau, der skal udfyldes. For eksempel, hvis du indstiller værdien af FILLFACTOR til 70 %, vil kun 70 % af den samlede plads på bladniveau-siden blive fyldt med indeksdata. De resterende 30 % vil blive tilbage til automatisk vækst af indeksdata i fremtiden.
5. Indekstyper
En anden ekstremt vigtig overvejelse i databaseindeksdesign er typen af indeks, der skal bruges. I en tidligere artikel (tilføj et link til artiklen "When to use Clustered or Non-Clustered Index") forklarede jeg forskellen mellem klyngede og ikke-klyngede indekser. Jeg forklarede også, hvad de er, og hvordan de kan bruges. Beslutningen om at vælge et klynget eller et ikke-klynget indeks er afgørende og bør gennemtænkes nøje.
Følgende punkter bør huskes, når du beslutter, hvilken indekstype du skal vælge.
- For de kolonner, der bruges i SELECT/JOIN/GROUP BY/BETWEEN-forespørgsler, skal du bruge klyngede indekser.
- Brug ikke-klyngede indekser til kolonner, hvor du kun ønsker at hente værdier fra den specifikke kolonne og ikke fra de andre kolonner i samme række. SELECT-forespørgsler, der henter flere poster ved hjælp af et ikke-klynget indeks, kan være langsomme, fordi SQL Server-maskinen først søger i kolonneværdierne, som indekset er oprettet på, og derefter ved hjælp af rækkereferencen for kolonneværdien, hentes posterne fra faktiske databasetabeller .
- For de kolonner, der ofte gennemgår INSERT- og UPDATE-operationer, skal du bruge et ikke-klynget indeks. Sørg for ikke at bruge én kolonne i flere ikke-klyngede indekser, da det kan forsinke opdateringsforespørgsler. Klyngede indekser kan være langsomme for INSERT/UPDATE-operationer, fordi hele rækken skal opdateres i stedet for kun en enkelt kolonneværdi, som det er tilfældet med ikke-klyngede indekser.
- Da du kun kan oprette ét klynget indeks, i deres tilfælde, hvor du har brug for flere indekser, skal du bruge ikke-klyngede indekser. Men hvis diskplads er et stort problem, skal du holde antallet af ikke-klyngede indekser på et minimum.
Andre overvejelser
Selvom disse er de fem vigtigste dele af databaseindeksdesign, er de ikke alt. Det er vigtigt at angive den korrekte rækkefølge af kolonnerne i indekser. Som en tommelfingerregel bør de kolonner, der bruges til beslutningstagning i WHERE-sætninger, og betingelser som større end (>), mindre end (<) osv. placeres før de kolonner, der ikke er involveret i disse klausuler. I tilfælde af flere kolonner i WHERE-sætningen, bør de mest karakteristiske kolonnenavne nævnes tidligst i indeksdefinitionen.
Bortset fra databaseindeksdesign spiller forespørgselsdesign også en vigtig rolle i den effektive brug af indeksdesign. For optimeret indeksvedligeholdelse i stedet for at skrive flere forespørgsler, der opererer på et lille antal rækker, kan du prøve at skrive færre forespørgsler, der påvirker et større antal tabelrækker.
Konklusion
Denne artikel forklarer nogle af de vigtigste overvejelser, som en databaseudvikler skal tage i betragtning, når han ser på databaseindeksdesign. Artiklen forklarer også rationalet bag disse overvejelser og indeholder yderligere forslag til at sikre, at dit databaseindeksdesign er effektivt.