Jeg har bemærket, at meget få mennesker forstår, hvordan indekser fungerer i SQL Server, især inkluderede kolonner. Ikke desto mindre er indekser den gode måde at optimere forespørgsler på. Først fik jeg heller ikke ideen om de inkluderede kolonner, men mine eksperimenter viste, at de er meget nyttige.
Antag, at vi har følgende tabel og forespørgsel:
CREATE TABLE Person ( PersonID int, FirstName varchar(100), LastName varchar(100), Age int, … … ) SELECT FirstName, LastName, Age FROM Person WHERE FirstName = 'John' and LastName = 'Smith'
Det er klart, at PersonID er en primær nøgle. Antag, at vi har et indeks med for- og efternavne, lad os kalde det IX_Person_FirstNameLastName. Udførelsesplanen for en sådan forespørgsel vil se som følger:
- Placering af alle linjerne med de angivne for- og efternavne ved hjælp af IX_Person_FirstNameLastName indekstræet
- Detektering af den faktiske placering af linjen på disken på indeksbladene, gå til den faktiske placering og aflæsning af alderen.
Lad os nu overveje, at denne forespørgsel udføres ret ofte. Vi skal udføre 2 trin hver gang. Kan det optimeres? I tilfælde af MS SQL Server er det ikke et problem - du kan inkludere værdier direkte i indekset ved hjælp af INCLUDE-indstillingen.
CREATE INDEX IX_PERSON ON Person ( FirstName, LastName ) INCLUDE(Age)
Nu bruges dette felt ikke under indeksering, men er inkluderet i indekset. Hvilke problemer kan vi stå over for i denne henseende? Når vi indekserer en tabel efter et bestemt felt, skal databaseserveren bygge et indekstræ efter dette felt. Det betyder, at vi skal ændre indekstræet, når vi ændrer værdien. Når værdier ændres intensivt, bliver det en problematisk og hård opgave for serveren. Når opdateringen bliver for omfattende, er det nogle gange lettere at droppe indekset. Indeks optimerer søgningen i høj grad, men påvirker indsættelses-, sletnings- og opdateringsoperationerne negativt.
Hvis et felt blot er inkluderet i et indeks, bruges det ikke under opbygningen af et indekstræ og påvirker det ikke, men værdi kan let findes på bladet af dette træ. Når en søgning på efter- og fornavn finder sted, søger serveren efter alle for- og efternavne fra træet, og når den når bladet (finder den nødvendige indeksværdi), så ud over markøren til den fysiske placering af linjeværdierne indeholder den også feltværdier, der er inkluderet i indekset. Det betyder, at der ikke er behov for at tage det andet trin for at skifte til den fysiske placering af linjen og læse den derfra.
Da du ikke behøver at ændre træet, når du ændrer aldersdataene, påvirker alt dette ikke meget dataændringsoperationerne. Vi behøver ikke at ændre indekset, vi skal bare ændre værdierne på træbladet. Det er derfor, at selv en massiv ændring af aldersfeltet ikke vil have stor indflydelse på præstationen. Det vil helt sikkert påvirke, men ikke så meget.
Så vidt jeg ved, er værdierne for det klyngede indeks automatisk inkluderet i bladniveauet, men dette skal kontrolleres med specifikationen.
Så hvornår er brugen af de inkluderede felter fordelagtig? Når de ofte bruges i forespørgselsresultater, men ændres en gang imellem. Et eksempel er en tabel over banktransaktioner. En sådan tabel kan bestå af følgende felter:kontonummer, transaktionstype, dato, sum. Det nytter ikke at indeksere med summen, men vi kan inkludere det i indekset, og det vil fremskynde forespørgslen markant.
For at hente den reelle effekt fra indeksering, bør forespørgslerne ikke vælge alle felter, dvs. vi bør glemme alt om SELECT * FROM table. Genberegn altid kun de felter, du virkelig har brug for. Og hvis deres værdier kommer til at være i indekset, kan eksekveringshastigheden være ret høj.
Nyttigt værktøj:
dbForge Index Manager – praktisk SSMS-tilføjelse til at analysere status for SQL-indekser og løse problemer med indeksfragmentering.