Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Защо Query Optimizer напълно игнорира индексираните индекси на изгледи?

tl;dr отговор:Ако не укажете NOEXPAND, оптимизаторът на заявките няма представа, че изпращате просто избиране от изглед. Ще трябва да съответства на разширяването на вашата заявка (което е всичко, което вижда) с някакъв индекс на изглед. Вероятно няма да се притеснява, когато е петпосочно присъединяване с куп отливки.

Съпоставянето на индекса на изглед към заявка е труден проблем и вярвам, че вашият изглед е твърде сложен, за да може машината за заявки да съответства на индекс. Считайте това за едно от вашите запитвания:

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

За вас е очевидно, че това може да използва индекс на изглед, но това не е заявката, която системата за заявки вижда. Изгледите се разширяват автоматично, ако не посочите NOEXPAND, така че това е, което отива в системата за заявки:

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;

Машината за заявки вижда тази сложна заявка и има информация (но вероятно не SQL на дефиниции на изгледи), която описва дефинираните индекси на изгледи. Като се има предвид, че и тази заявка, и индексите на изгледа имат множество присъединявания и прехвърляния, съвпадението е трудна работа.

Имайте предвид, че знаете, че присъединяванията и съвпаденията са идентични в тази заявка и индексите на изгледа, но процесорът за обработка на заявки не знае това. Той третира тази заявка по същия начин, както ако обедини пет копия на Classificator3 или ако една от колоните е 'NQ'+CAST(c2.CODE като varchar(12)). Съпоставящият индекс на изглед (ако приемем, че е направил някакъв опит да съпостави тази сложна заявка) ще трябва да съпостави всеки детайл от тази заявка с подробностите на индексите на изглед на включените таблици.

Машината за заявки има за своя цел №1 да открие начин за ефективно изпълнение на заявката. Вероятно не е проектиран да прекарва много време в опити да съпостави всеки детайл от петстранно присъединяване и CASTs към индекс на изглед.

Ако трябваше да гадая, подозирам, че съвпадението на индекса на изгледа вижда, че колоните с резултати на заявката дори не са колони на която и да е основна таблица (поради CAST) и просто не си прави труда да опитва нищо. Добавено :Грешам. Току-що опитах предложението на Мартин за актуализиране на статистиката, за да направя заявката скъпа, и беше съпоставен индекс на изглед за някои от тези заявки без NOEXPAND. Изгледът за съвпадение е по-умен, отколкото си мислех! Така че проблемът е, че инструментът за съпоставяне на изгледи вероятно се опитва по-усилено да съпостави сложна заявка, ако цената му е много висока.

Използвайте подсказката NOEXPAND, вместо да очаквате машината за заявки да може да разбере какво съвпада тук. NOEXPAND е абсолютно ваш приятел, защото тогава машината за заявки може да види

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

и след това веднага става очевидно за съпоставителя на изглед индекс, че има полезен индекс.

(Забележка:Вашият SQL Fiddle код има всичките 5 препратки към външен ключ към една и съща таблица, което вероятно не е това, което искате.)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. ADO.NET извикването на T-SQL Stored Procedure причинява SqlTimeoutException

  2. Sql сървър:Как да използвате агрегатна функция като MAX в клауза WHERE

  3. Обработка на отрицателни стойности с sql

  4. Как да създам колона, изчислена от друга колона?

  5. Стартирайте всички SQL файлове в директория