sql >> Database >  >> RDS >> Sqlserver

Waarom is dit een indexscan en geen indexzoekopdracht?

Het gebruikt een Index Scan voornamelijk omdat het ook een Merge Join gebruikt. De operator Samenvoegen vereist twee invoerstromen die beide zijn gesorteerd in een volgorde die compatibel is met de voorwaarden voor samenvoegen.

En het gebruikt de Merge Join-operator om je INNER JOIN te realiseren, omdat het gelooft dat dit sneller zal zijn dan de meer typische Nested Loop Join-operator. En het is waarschijnlijk juist (meestal is het), door gebruik te maken van de twee indexen die het heeft gekozen, heeft het invoerstromen die beide zijn voorgesorteerd volgens uw join-voorwaarde (LocationID). Als de invoerstromen op deze manier zijn voorgesorteerd, zijn Merge Joins bijna altijd sneller dan de andere twee (Loop en Hash Joins).

Het nadeel is wat je hebt opgemerkt:het lijkt alsof de hele index wordt gescand, dus hoe kan dat sneller als het zoveel records leest die misschien nooit worden gebruikt? Het antwoord is dat scans (vanwege hun sequentiële aard) overal 10 tot 100 keer zoveel records per seconde kunnen lezen als wordt gezocht.

Nu wint Seeks meestal omdat ze selectief zijn:ze krijgen alleen de rijen waar je om vraagt, terwijl Scans niet-selectief zijn:ze moeten elke rij in het bereik retourneren. Maar omdat Scans een veel . hebben hogere leessnelheid, ze kunnen vaak beter dan Zoekt, zolang de verhouding van weggegooide rijen tot overeenkomende rijen lager is dan de verhouding van Scan rijen/sec VS. Zoek rijen/sec.

Vragen?

OK, ik ben gevraagd om de laatste zin meer uit te leggen:

Een "Verworpen rij" is er een die door de Scan wordt gelezen (omdat het alles in de index moet lezen), maar dat wordt afgewezen door de operator Samenvoegen Samenvoegen, omdat het geen overeenkomst heeft aan de andere kant, mogelijk omdat de WHERE-clausulevoorwaarde heeft het al uitgesloten.

"Overeenkomende rijen" zijn de rijen die worden gelezen die daadwerkelijk overeenkomen met iets in de samenvoegverbinding. Dit zijn dezelfde rijen die een Seek zou hebben gelezen als de Scan was vervangen door een Seek.

U kunt erachter komen wat er zijn door te kijken naar de statistieken in het Queryplan. Zie je die enorme dikke pijl links van de Index Scan? Dat geeft aan hoeveel rijen de optimizer denkt te zullen lezen met de Scan. Het statistiekvak van de Indexscan die u hebt gepost, laat zien dat de werkelijke geretourneerde rijen ongeveer 5,4 miljoen (5.394.402) bedragen. Dit is gelijk aan:

TotalScanRows = (MatchingRows + DiscardedRows)

(In mijn bewoordingen in ieder geval). Om de overeenkomende rijen te krijgen, kijkt u naar de "werkelijke rijen" gerapporteerd door de operator Samenvoegen samenvoegen (mogelijk moet u de TOP 100 verwijderen om dit nauwkeurig te krijgen). Als u dit eenmaal weet, kunt u de rijen Afgedankt krijgen door:

DiscardedRows = (TotalScanRows - MatchingRows)

En nu kun je de verhouding berekenen.



  1. Hoe selecteer ik slechts één generatie van een hiërarchische boom met behulp van een bovenliggende onderliggende tabelrelatie met SQL?

  2. Hoe te BESTELLEN OP EEN SOM() in MySQL?

  3. Bedrijfslogica:database- of applicatielaag

  4. SQL kruisverwijzingen naar een andere tabel om gegevens te controleren