web-dev-qa-db-fra.com

Pourquoi le processeur de requête ne peut-il pas produire un plan de requête avec un indice de Faumes lorsque je suis une jonction intérieure par l'index en cluster sur les deux vues indexées?

Je reçois l'erreur suivante lorsque j'essaie d'utiliser l'indice des Faumes avec la requête ci-dessous:

MSG 8622, niveau 16, l'état 1, le processeur de requête de la ligne 96 n'a pas pu produire de plan de requête en raison des indices définis dans cette requête. Soumettez à nouveau la requête sans spécifier de conseils et sans utiliser Set ForcePlan.

SELECT A.IndexedField1
INTO #TEMP
FROM dbo.IndexedView1 AS A WITH (FORCESEEK)
INNER JOIN dbo.IndexedView2 AS B
    ON A.IndexedField1 = B.IndexedField1
    AND A.IndexedField2 = B.IndexedField2

IndexedView1 et IndexedView2 sont à la fois des vues d'indexation schémas et une index clustere unique sur les deux vues sur les champs indexedfield1, indexedfield2. Je ne sais pas le cas échéant, mais l'index en clustere est de 40 octets gros (par ligne).

Voici un exemple de exactement ce que les deux vues ressemblent sous le capot:

SELECT 
    IndexedField1,
    RIGHT(CONVERT(VARCHAR(34), HASHBYTES('MD5', OtherField1 + '||' OtherField2)), 32) AS IndexedField2
FROM dbo.Table1

Rien de trop chic, et pas de notes à l'intérieur de la requête de la vue.

C'est le plan d'exécution estimé (sans tenter d'utiliser un indice de requête): Estimated Execution Plan

2
J.D.

Voici une repro. C'est documenté que vous ne pouvez pas utiliser FRESSEEK sur une vue indexée sans NOEXPAND .

PAR EXEMPLE

drop table if exists table1
drop table if exists table2
go
create table Table1(IndexedField1 int, OtherField1 nvarchar(200), OtherField2 nvarchar(200))
create table Table2(IndexedField1 int, OtherField1 nvarchar(200), OtherField2 nvarchar(200))

go

create view IndexedView1
with schemabinding
as
SELECT 
    IndexedField1,
    RIGHT(CONVERT(VARCHAR(34), HASHBYTES('MD5', OtherField1 + '||' + OtherField2)), 32) AS IndexedField2
FROM dbo.Table1

go

create view IndexedView2
with schemabinding
as
SELECT 
    IndexedField1,
    RIGHT(CONVERT(VARCHAR(34), HASHBYTES('MD5', OtherField1 + '||' + OtherField2)), 32) AS IndexedField2
FROM dbo.Table2

go

create unique clustered index pk_IndexedView1 on IndexedView1(IndexedField1,IndexedField2)
create unique clustered index pk_IndexedView2 on IndexedView2(IndexedField1,IndexedField2)

go

SELECT A.IndexedField1
INTO #TEMP
FROM dbo.IndexedView1 AS A WITH (FORCESEEK)
INNER JOIN dbo.IndexedView2 AS B
    ON A.IndexedField1 = B.IndexedField1
    AND A.IndexedField2 = B.IndexedField2

    /*
Msg 8622, Level 16, State 1, Line 34
Query processor could not produce a query plan because of the hints defined in this query. Resubmit the query without specifying any hints and without using SET FORCEPLAN.
*/
go
drop table if exists #TEMP

SELECT A.IndexedField1
INTO #TEMP
FROM dbo.IndexedView1  AS A with (noexpand)
INNER JOIN dbo.IndexedView2 AS B with (noexpand)
    ON A.IndexedField1 = B.IndexedField1
    AND A.IndexedField2 = B.IndexedField2

exécute avec plan:

enter image description here

Et après avoir appliqué NOEXPAND, et précisant que le plan ne doit impliquer que les indices de vue, vous pouvez ensuite utiliser l'indice FRESSEK, ou spécifier le style de jointure (fusion, boucle ou hachage) si vous le souhaitez.

PAR EXEMPLE

SELECT A.IndexedField1
INTO #TEMP
FROM dbo.IndexedView1 AS A WITH (NOEXPAND)
INNER MERGE JOIN dbo.IndexedView2 AS B
    ON A.IndexedField1 = B.IndexedField1
    AND A.IndexedField2 = B.IndexedField2
4