sql >> Databasteknik >  >> RDS >> Sqlserver

Varför är detta en indexsökning och inte en indexsökning?

Den använder en Index Scan främst för att den också använder en Merge Join. Operatören Merge Join kräver två indataströmmar som båda är sorterade i en ordning som är kompatibel med Join-villkoren.

Och den använder Merge Join-operatören för att realisera din INNER JOIN eftersom den tror att den kommer att vara snabbare än den mer typiska Nested Loop Join-operatören. Och det är förmodligen rätt (det brukar vara det), genom att använda de två indexen som den har valt har den ingångsströmmar som båda är försorterade enligt ditt anslutningsvillkor (LocationID). När ingångsströmmarna är försorterade så här, är Merge Joins nästan alltid snabbare än de andra två (Loop och Hash Joins).

Nackdelen är vad du har märkt:det verkar skanna hela indexet in, så hur kan det gå snabbare om det läser så många poster som kanske aldrig kommer att användas? Svaret är att skanningar (på grund av deras sekventiella karaktär) kan läsa allt från 10 till 100 gånger så många poster/sekund som sökningar.

Now Seeks vinner vanligtvis eftersom de är selektiva:de får bara de rader som du ber om, medan skanningar är icke-selektiva:de måste returnera varje rad i intervallet. Men eftersom skanningar har mycket högre läsfrekvens kan de ofta slå Seeks så länge förhållandet mellan kasserade rader och matchande rader är lägre än förhållandet Scan rader/sek VS. Sök rader/sek.

Frågor?

OK, jag har blivit ombedd att förklara den sista meningen mer:

En "Discarded Row" är en som skanningen läser (eftersom den måste läsa allt i indexet), men som kommer att avvisas av Merge Join-operatören, eftersom den inte har en matchning på andra sidan, möjligen för att WHERE-klausulens villkor har redan uteslutit det.

"Matchande rader" är de som det läses som faktiskt matchas med något i Merge Join. Det här är samma rader som skulle ha lästs av en sökning om sökningen hade ersatts av en sökning.

Du kan ta reda på vad det finns genom att titta på statistiken i frågeplanen. Ser du den stora feta pilen till vänster om Index Scan? Det representerar hur många rader optimeraren tror att den kommer att läsa med Scan. Statistikrutan för Indexskanningen som du lade upp visar att de faktiska raderna som returneras är cirka 5,4 miljoner (5 394 402). Detta är lika med:

TotalScanRows = (MatchingRows + DiscardedRows)

(I alla fall enligt mina termer). För att få matchande rader, titta på "Faktiska rader" som rapporterats av Merge Join-operatören (du kan behöva ta av TOP 100 för att få detta korrekt). När du väl vet detta kan du få de Kasserade raderna genom att:

DiscardedRows = (TotalScanRows - MatchingRows)

Och nu kan du beräkna förhållandet.



  1. Korstabellbegränsningar i PostgreSQL

  2. SQL-fråga - Ta bort dubbletter om fler än 3 dubbletter?

  3. Rekursiv mysql select?

  4. Inkluderar Custom SELECT-satsen i ActiveRecord-frågan