sql >> Databasteknik >  >> RDS >> Sqlserver

Skapa mer än ett icke-klustrat index på samma kolumn i SQL Server

Orden är ganska logiska och du lär dig dem ganska snabbt. :)

I lekmannatermer innebär SEEK att man söker efter exakta platser för poster, vilket är vad SQL Server gör när kolumnen du söker i är indexerad och ditt filter (WHERE-villkoret) är tillräckligt korrekt.

SCAN innebär ett större antal rader där frågeexekveringsplaneraren uppskattar att det går snabbare att hämta ett helt intervall i motsats till att söka varje värde individuellt.

Och ja, du kan ha flera index på samma fält, och ibland kan det vara en mycket bra idé. Spela ut med indexen och använd exekveringsplaneraren för att avgöra vad som händer (genväg i SSMS:Ctrl + M). Du kan till och med köra två versioner av samma fråga och exekveringsplaneraren visar dig enkelt hur mycket resurser och tid som tas av var och en, vilket gör optimeringen ganska enkel.

Men för att utöka dessa lite, säg att du har en sådan adresstabell och den har över 1 miljard poster:

CREATE TABLE ADDRESS 
  (ADDRESS_ID INT -- CLUSTERED primary key ADRESS_PK_IDX
  , PERSON_ID INT -- FOREIGN KEY, NONCLUSTERED INDEX ADDRESS_PERSON_IDX
  , CITY VARCHAR(256)
  , MARKED_FOR_CHECKUP BIT
  , **+n^10 different other columns...**)

Om du nu vill hitta all adressinformation för person 12345, är indexet på PERSON_ID perfekt. Eftersom tabellen har massor av andra data på samma rad, skulle det vara ineffektivt och utrymmeskrävande att skapa ett icke-klustrat index för att täcka alla andra kolumner såväl som PERSON_ID. I det här fallet kommer SQL Server att köra ett index SEEK på indexet i PERSON_ID och sedan använda det för att göra en nyckelsökning på det klustrade indexet i ADDRESS_ID och därifrån returnera all data i alla andra kolumner på samma rad.

Säg dock att du vill söka efter alla personer i en stad, men att du inte behöver annan adressinformation. Den här gången skulle det mest effektiva sättet vara att skapa ett index på CITY och använda INCLUDE-alternativet för att även täcka PERSON_ID. På så sätt skulle en enda indexsökning/skanning returnera all information du behöver utan att behöva kontrollera CLUSTERED-indexet för PERSON_ID-data på samma rad.

Låt oss nu säga att båda dessa frågor är nödvändiga men fortfarande ganska tunga på grund av de 1 miljard poster. Men det finns en speciell fråga som måste vara riktigt riktigt snabb. Den frågan vill ha alla personer på adresser som har blivit MARKED_FOR_CHECKUP och som måste bo i New York (ignorera vad kontroll betyder, det spelar ingen roll). Nu kanske du vill skapa ett tredje, filtrerat index på MARKED_FOR_CHECKUP och CITY, med INCLUDE som täcker PERSON_ID, och med ett filter som säger CITY ='New York' och MARKED_FOR_CHECKUP =1. Det här indexet skulle vara vansinnigt snabbt, eftersom det bara täcker frågor som uppfyller de exakta villkoren och därför har en bråkdel av data att gå igenom jämfört med de andra indexen.

(Ansvarsfriskrivning här, kom ihåg att exekveringsplaneraren inte är dum, den kan använda flera icke-klustrade index tillsammans för att producera rätt resultat, så exemplen ovan kanske inte är de bästa tillgängliga eftersom det är väldigt svårt att föreställa sig när du skulle behöva 3 olika index som täcker samma kolumn, men jag är säker på att du förstår idén.)

Typerna av index, deras kolumner, inkluderade kolumner, sorteringsordningar, filter etc beror helt på situationen. Du kommer att behöva göra täckande index för att tillfredsställa flera olika typer av frågor, såväl som anpassade index som skapats specifikt för enstaka, viktiga frågor. Varje index tar upp plats på hårddisken så att göra onödiga index är slösaktigt och kräver extra underhåll när datamodellen ändras, och slösar dock tid på defragmentering och statistikuppdatering... så du vill inte bara slänga ett index på allt. antingen.

Experimentera, lär dig och ta reda på vilket som fungerar bäst för dina behov.



  1. Rails Postgresql flera scheman och samma tabellnamn

  2. SocketException :Ingen sådan värd är känd

  3. sql-fråga för att ersätta city pune till mumbai och mumbai till pune i tabellen

  4. MySqlCommand().ExecuteReader().GetString() fungerar inte