sql >> Databáze >  >> RDS >> Sqlserver

Proč Optimalizátor dotazů zcela ignoruje indexy indexovaných zobrazení?

Odpověď tl;dr:Pokud nezadáte NOEXPAND, optimalizátor dotazů netuší, že odesíláte jednoduchý výběr z pohledu. Muselo by to odpovídat rozšíření vašeho dotazu (což je vše, co vidí) s nějakým indexem zobrazení. Pravděpodobně to nebude vadit, když je to pěticestné spojení s hromadou odhozů.

Přiřazení indexu zobrazení k dotazu je obtížný problém a domnívám se, že váš pohled je příliš komplikovaný na to, aby se dotazovací stroj mohl shodovat s indexem. Zvažte tento jeden z vašich dotazů:

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

Je vám zřejmé, že to může používat index zobrazení, ale toto není dotaz, který dotazovací modul vidí. Zobrazení se automaticky rozbalí, pokud nezadáte NOEXPAND, takže dotazovací stroj přejde takto:

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;

Dotazovací stroj vidí tento komplikovaný dotaz a má informace (ale pravděpodobně ne SQL definic zobrazení), které popisují indexy zobrazení, které byly definovány. Vzhledem k tomu, že tento dotaz i indexy zobrazení mají více spojení a přetypování, je shoda obtížná.

Mějte na paměti, že víte, že spojení a shody jsou v tomto dotazu a indexech zobrazení identické, ale procesor dotazů to neví. Zachází s tímto dotazem úplně stejně, jako kdyby spojil pět kopií Classificator3, nebo kdyby jeden ze sloupců byl 'NQ'+CAST(c2.CODE jako varchar(12)). Nástroj pro vyhledávání indexů zobrazení (za předpokladu, že by se pokusil porovnat tento komplikovaný dotaz) by musel porovnat každý detail tohoto dotazu s podrobnostmi indexů zobrazení v příslušných tabulkách.

Dotazovací stroj má za cíl číslo 1 přijít na způsob, jak efektivně provést dotaz. Pravděpodobně není navržen tak, aby trávil spoustu času snahou porovnat každý detail pěticestného spojení a CAST s indexem zobrazení.

Pokud bych měl hádat, mám podezření, že nástroj pro vyhledávání indexů vidí, že výsledné sloupce dotazu nejsou ani sloupci žádné podkladové tabulky (kvůli CAST) a jednoduše se neobtěžuje nic zkoušet. Přidáno :Mýlím se. Právě jsem zkusil Martinův návrh aktualizovat statistiky, aby byl dotaz drahý, a pro některé z těchto dotazů byl porovnán index zobrazení bez NOEXPAND. Porovnávač zobrazení je chytřejší, než jsem si myslel! Problém je tedy v tom, že přiřazovač zobrazení se pravděpodobně více snaží porovnat komplikovaný dotaz, pokud je jeho cena velmi vysoká.

Použijte nápovědu NOEXPAND namísto očekávání, že dotazovací stroj bude schopen zjistit, co se zde shoduje. NOEXPAND je absolutně váš přítel, protože pak dotazovací modul uvidí

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

a nástroji pro vyhledávání indexů je pak okamžitě zřejmé, že existuje užitečný index.

(Poznámka:Váš kód SQL Fiddle má všech 5 odkazů na cizí klíč na stejnou tabulku, což pravděpodobně není to, co chcete.)



  1. ukládání čísel jako varchar

  2. výchozí pro sloupec xxxx nelze automaticky přetypovat na typ boolean v Postgres DB

  3. Jsou vyžadována oprávnění pro 'CREATE USER' v SQL Server 2005?

  4. zápis na sql server z C#, nevrátily se žádné chyby