sql >> Database >  >> RDS >> Sqlserver

Waarom negeert Query Optimizer geïndexeerde weergave-indexen volledig?

tl;dr antwoord:Als u NOEXPAND niet opgeeft, heeft de query-optimizer geen idee dat u een eenvoudige selectie uit een weergave verzendt. Het zou moeten overeenkomen met de uitbreiding van uw zoekopdracht (dat is alles wat het ziet) met een of andere weergave-index. Zal waarschijnlijk niet de moeite nemen als het een vijf-weg join is met een stel casts.

Het matchen van de weergave-index met een zoekopdracht is een moeilijk probleem, en ik denk dat uw weergave te ingewikkeld is voor de zoekengine om te matchen met een index. Beschouw dit als een van uw vragen:

SELECT ID, Code1 FROM EntityView Where Code1 > 'NR%';

Het is duidelijk voor u dat dit een weergave-index kan gebruiken, maar dit is niet de zoekopdracht die de query-engine ziet. Weergaven worden automatisch uitgebreid als u NOEXPAND niet opgeeft, dus dit gaat naar de query-engine:

SELECT ID, Code1 FROM (
    SELECT e.ID, 'NR'+CAST(c1.CODE as nvarchar(11)) as Code1, 'NR'+CAST(c2.CODE as nvarchar(11)) as Code2, 'NR'+CAST(c3.CODE as nvarchar(11)) as Code3, 'NR'+CAST(c4.CODE as nvarchar(11)) as Code4, 'NR'+CAST(c5.CODE as nvarchar(11)) as Code5
    FROM dbo.Entity e
        inner join  dbo.Classificator1 c1 on e.ID = c1.ID
        inner join  dbo.Classificator2 c2 on e.ID = c2.ID
        inner join  dbo.Classificator3 c3 on e.ID = c3.ID
        inner join  dbo.Classificator4 c4 on e.ID = c4.ID
        inner join  dbo.Classificator5 c5 on e.ID = c5.ID;
) AS V;

De query-engine ziet deze gecompliceerde query en heeft informatie (maar waarschijnlijk geen SQL van weergavedefinities) die de gedefinieerde weergave-indexen beschrijven. Aangezien deze query en de weergave-indexen beide meerdere joins en casts hebben, is het een lastige klus om te matchen.

Houd er rekening mee dat u weet dat de joins en overeenkomsten identiek zijn in deze query en de view-indexen, maar de queryprocessor weet dat niet. Het behandelt deze vraag op dezelfde manier alsof het vijf exemplaren van Classificator3 zou samenvoegen, of als een van de kolommen 'NQ'+CAST(c2.CODE as varchar(12)) was. De view index matcher (ervan uitgaande dat hij enige poging heeft gedaan om deze ingewikkelde zoekopdracht te matchen) zou elk detail van deze zoekopdracht moeten afstemmen op de details van de view-indexen op de betrokken tabellen.

De query-engine heeft als belangrijkste doel een manier te vinden om de query efficiënt uit te voeren. Het is waarschijnlijk niet ontworpen om veel tijd te besteden aan het matchen van elk detail van een vijfvoudige join en CAST's aan een weergave-index.

Als ik moest raden, vermoed ik dat de view index matcher ziet dat de resultaatkolommen van de query niet eens kolommen zijn van een onderliggende tabel (vanwege de CAST) en gewoon niet de moeite neemt om iets te proberen. Toegevoegd :Ik heb het mis. Ik heb net Martin's suggestie geprobeerd om statistieken bij te werken om de zoekopdracht duur te maken, en voor sommige van deze zoekopdrachten werd een weergave-index gematcht zonder NOEXPAND. De view matcher is slimmer dan ik dacht! Het probleem is dus dat de view matcher waarschijnlijk harder probeert om een ​​gecompliceerde zoekopdracht te matchen als de kosten erg hoog zijn.

Gebruik de NOEXPAND-hint in plaats van te verwachten dat de query-engine kan achterhalen wat hier overeenkomt. NOEXPAND is absoluut je vriend, want dan krijgt de query-engine te zien

SELECT ID, Code1 FROM EntityView Where Code1 > 'NR%';

en het is dan meteen duidelijk voor de view index matcher dat er een bruikbare index is.

(Opmerking:uw SQL Fiddle-code heeft alle 5 refererende sleutelverwijzingen naar dezelfde tabel, wat waarschijnlijk niet is wat u wilt.)



  1. NU() instellen als standaardwaarde voor datatype datetime?

  2. SSMS geeft systeemgeheugen niet vrij

  3. Records van de afgelopen 24 uur selecteren in PostgreSQL

  4. SQL Server trigger verwijderen of trapsgewijs verwijderen