Pourquoi l'indication READPAST provoque-t-elle l'ignorance des vues indexées?

10

J'étudie l'utilisation de l' READPASTindice pour réduire le verrouillage des ressources dans le sous-système financier de notre application.

Cela semblait être une bonne façon de procéder, car les enregistrements de transactions financières ne sont jamais ajoutés, jamais mis à jour ou supprimés. Les seules lignes qui pourraient être ignorées sont les nouvelles lignes insérées à l'intérieur d'une transaction; ils n'existent effectivement pas dans le monde extérieur tant que la transaction n'est pas validée.

Cependant, j'ai remarqué des performances moins bonnes sur les requêtes qui utilisent des vues indexées sur lesquelles j'avais donné un READPASTindice. En comparant les plans de requête, il semble qu'avec l'indicateur, l'optimiseur de requête choisit de ne pas utiliser la vue indexée et revient à la traiter comme une vue normale.

Je ne sais pas pourquoi ce serait; J'imagine que les vues indexées sont comme tout autre index dans la mesure où les clés peuvent être verrouillées pendant les opérations et l'ajout READPASTfonctionnerait de la même manière.

SELECT TOP 1 isa.InvoiceId
FROM Financial_InvoiceSummaryAmounts isa WITH (READPAST)
WHERE isa.TotalOwedAmount = 0.0

entrez la description de l'image ici

SELECT TOP 1 isa.InvoiceId
FROM Financial_InvoiceSummaryAmounts isa
WHERE isa.TotalOwedAmount = 0.0

entrez la description de l'image ici

L'ajout d'un NOEXPANDindice semble également fonctionner, mais je souhaite en savoir plus sur les raisons pour lesquelles READPASTl'optimiseur de requêtes a fait ce choix en premier lieu (dans le cadre d'une réponse complète).

Mars
la source

Réponses:

7

Réutilisation de l'exemple de table et de vue indexée de mon article Another Reason to Use NOEXPANDhints in Enterprise Edition :

CREATE TABLE dbo.T
(
    col1 integer NOT NULL
);
GO
INSERT dbo.T WITH (TABLOCKX)
    (col1)
SELECT 
    SV.number
FROM master.dbo.spt_values AS SV
WHERE 
    SV.type = N'P';
GO
CREATE VIEW dbo.VT
WITH SCHEMABINDING
AS
SELECT T.col1 
FROM dbo.T AS T;

Repro

Cette requête correspond à la vue indexée (bien qu'avec un agrégat redondant):

SELECT DISTINCT
    VT.col1 
FROM dbo.VT AS VT;

Vue indexée correspondante

L'ajout d'un READPASTindice entraîne l'accès à la table de base:

SELECT DISTINCT
    VT.col1 
FROM dbo.VT AS VT 
    WITH (READPAST);

La vue indexée ne correspond pas

Explication

L' READPASTallusion est sémantique. L'optimiseur résiste à la réécriture des requêtes de sorte que les résultats changent. Pour illustrer:

La requête suivante s'exécute sans problème:

SELECT DISTINCT
    VT.col1 
FROM dbo.VT AS VT 
    WITH (READPAST);

Pourtant:

SELECT DISTINCT
    VT.col1 
FROM dbo.VT AS VT 
    WITH (READPAST)
OPTION 
    (TABLE HINT (VT, FORCESCAN));

Produit l'erreur:

Msg 8722, niveau 16, état 1, ligne 42
Impossible d'exécuter la requête.
Un indice affectant la sémantique «readpast» apparaît dans la clause «WITH» de l'objet «VT»
mais pas dans la clause 'TABLE HINT' correspondante.
Modifiez la clause OPTION (TABLE HINTS ...) afin que les indices affectant la sémantique
correspondre à la clause WITH.

Lorsque vous référencez la vue indexée sans l' NOEXPANDindication, la vue est développée (avant le début de la compilation et de l'optimisation) pour référencer les objets sous-jacents à la place. Plus tard dans le processus, l'optimiseur peut envisager de faire correspondre l'arborescence des requêtes à une vue indexée, en tout ou en partie.

Quand READPASTest utilisé sans NOEXPAND, le conseil se propage à la table de base, empêchant la correspondance de vue (sémantique différente).

Avec NOEXPAND, l'indice s'applique directement à la vue, il n'y a donc pas de problème.

Paul White 9
la source