SQL Server på svenska
En svensk blogg om SQL Server, skriven på svenska. Kodexempel, fördjupningar och reflexioner på vad som händer i SQL Server-världen


.NET (1) BLOB (1) Bloggen (2) DBA (2) Design (1) Felhantering (1) Installation (1) Optimering (4) Säkerhet (1) SQL Server 2000 (2) SQL Server 2005 (2) SQL Server 2008 (1)


 Friday, April 18, 2008
« Installation av SQL Server 2005 hän... | Main | Att jämföra exakt och ungef&au... »
Vaddå klusterindex?

Fler än en gång har jag försökt att grundläggande förklara lite grann om index i SQL Server (och egentligen alla andra databaser, det funkar ju faktiskt rätt lika). Det som flest har svårt att förstå är det här med klustrade och icke-klustrade index. Många undrar vad som är skillnaden, och många undrar vilket index som är bästa kandidaten att använda som klustrat index. Här tänkte jag försöka sammanfatta vad jag brukar svara.

Vad är det?
Ett klustrat index är ett index som lagras tillsammans med datat för en tabell. Det gör att datat självt är sorterat, vilket kan vara användbart emellanåt.

Den bästa jämförelsen jag känner till är en telefonkatalog. I en telefonkatalog finns sidor, som vi kan jämföra med data-pages i SQL Server. Varje telefonnummer kan jämföras med en rad i en tabell i SQL Server. Telefonnumren är sorterade efter Efternamn, Förnamn. På samma sätt funkar ett klustrat index. Datat på varje data-page är sorterat efter det klustrade indexet som finns på tabellen. Tabellens data-pages är sorterade inbördes enligt samma princip.

I SQL Server finns dessutom ett index-träd utanför tabellen som gör att det blir lite lättare att hitta till den första raden som uppfyller ett sökvillkor i det klustrade indexet. Det kan jämföras med att högerkanten på sidorna i en telefonkatalog ofta innehåller ett första-bokstaven-register, som ger genvägar till alla efternamn som börjar på en viss bokstav.

Har du en tabell med telefonnummer, Efternamn och Förnamn, där Efternamn, Förnamn är ett klustrat index, och du vill söka ut alla telefonnummer tillhörande någon som heter Andersson, så lägger du in "WHERE efternamn = 'Andersson'" som WHERE-klausul i din fråga. SQL Server börjar då leta i sitt index-träd efter 'Andersson', och när den hittar 'Andersson' så går den via en adress-pekare direkt till den data-page där den första förekomsten av 'Andersson' finns. Eftersom datat är sorterat efter Efternamn, Förnamn finns nu ingen anledning att gå tillbaka till något ytterligare index för att hitta alla rader för med Efternamn='Andersson', utan SQL Server kan börja läsa data-page efter data-page, tills den stöter på ett efternamn som INTE är 'Andersson'.

Icke-klustrat då?
Icke-klustrade index lagras helt och hållet utanför själva datat för en tabell. De lagras också i trädstrukturer, men innehåller till skillnad från klustrade index ett index-löv för varje rad i tabellen, och en pekare till adressen där raden lagras. Vill du läsa alla som heter 'Andersson' enigt exemplet ovan får SQL Server jobba lite mer för att hitta allt data. Den måste göra följande fler-stegs-raket:

  1. Leta upp första lövet/nästa löv med efternamn='Andersson' i indexträdet.
  2. Följ pekaren till den data-pagen där raden som index-lövet motsvarar lagras.
  3. Stoppa in raden i en temporär "Spool-tabell"
  4. Upprepa steg 1-3 tills alla 'Andersson' är funna
  5. Läs "Spool-tabellen" och returnera.

Alltså något mer arbete än att bara leta reda på den första raden och sen läsa och returnera rad för rad.

Vad ska jag välja som klustrat index?
När man börjar diskutera kandidater för klustrade index ändras ofta diskussionen till att bli av religiös karaktär.

SQL Server skapar alltid ett klustrat index, oavsett om vi vill det eller inte. Om vi inte själva bestämmer vilket index som ska vara klustrat skapas ett "osynligt" klustrat index som vi inte har varken nytta av eller kontroll över. Därför är det hyfsat självklart att vi ska välja ett klustrat index. Som standard skapar SQL Server ett klustrat index över kolumnen eller kolumnerna som ingår i primärnyckeln, om det inte redan finns ett klustrat index när primärnyckeln skapas.

Vissa hävdar att det här alltid är helt rätt och att man aldrig ska använda sig av annat än primärnyckeln som klustrat index. Det är snick-snack i mina öron. Tänk dig återigen fallet med telefonkatalogen. Man kan tänka sig att telefonnummer är primärnyckel i en telefonkatalog, eller hur? Varför skulle vi vilja ha telefonnummer som klustrat index i telefonkatalogen? Din Del skulle förmodligen ha betydligt färre nöjda mottagare av katalogen om den var sorterad efter telefonnummer..

Vissa hävdar att man ska ha HÖG selektivitet på det index som är klustrat. Dvs att man får träff på väldigt få rader om man söker i indexet efter ett visst värde. Varför det skulle vara en fördel förstår jag ärligt talat inte. Har man hög selektivitet på ett index, till exempel en primärnyckel, så kostar det ju väldigt lite att först söka reda på index-lövet och sen besöka en eller ett fåtal rader via pekare. Har man däremot LÅG selektivitet (exempelvis efternamn i en telefonkatalog) så kostar det ganska mycket att gå via ett icke-klustrat index.

Jag tycker att främmande nycklar ofta utgör bra kandidater för klustrade index. Tänker dig en order-applikation, med en Order-tabell och en Order-rad-tabell. Där vill man väldigt ofta selektera ut alla orderrader som tillhör ett visst ordernummer. Då är Ordernummer-kolumnen i orderrad-tabellen en perfekt kandidat för klustrat index. Nu skulle jag i och för sig designa min tabell så att primärnyckeln bestod av Order-nummer och Orderrad-nummer. Men många SQL Server-utvecklare använder sig ALDRIG av naturliga nycklar, utan skapar istället en IDENTITY-kolumn som primärnyckel. Den kolumnen är precis värdelös att använda som klustrat index, ur sökbarhetssynpunkt.

Sammanfattningsvis
Tänk dig för innan du bara accepterar SQL Servers förslag att skapa klustrat index av primärnyckeln. Använder du dig av normaliserade tabeller, med bara naturliga nycklar är det förmodligen bra kandidater för klustrade index. Men om du tillhör de 99% SQL Server-utvecklare som istället skapar en surrogat-nyckel och en UNIQUE-constraint (VARFÖR GÖR FÖRRESTEN SÅ MÅNGA DET, DET ÄR VERKLIGEN DUBBELARBETE!!!) över det som kunde varit naturlig nyckel - ja då ska du fundera både en och två gånger på vilket klustrat index du bör använda. Tänk telefonkatalog!

Intressant?
Andra bloggar om SQL Server, Databaser, Index, Klustrade index

Comments [0]   Kategorier: Optimering

Name
E-mail
Home page

Comment (Some html is allowed: a@href@title, strike) where the @ means "attribute." For example, you can use <a href="" title=""> or <blockquote cite="Scott">.  

Enter the code shown (prevents robots):

Live Comment Preview

Top Datorer bloggar
Bloggar.Topplista.se - topplistan med de b�sta bloggarna - l�gg till din blogg du ocks�!
BlogRankers.com
Bloggtoppen.se
Datorer
BloggRegistret.se




Total Posts: 14
This Year: 2
This Month: 0
This Week: 0
Comments: 65