2016-04-01 4 views
1

Je suis en train de tester les performances d'une vue indexée. Voici les codes que j'ai utilisés. J'utilise la base de données AdventureWorks2012.Pourquoi la vue indexée n'améliore pas les performances?

tables de test --create

SELECT * 
    INTO Person.Person_Test 
    FROM [Person].[Person] 
    go 
    SELECT * 
    INTO Person.PersonPhone_Test 
    FROM [Person].[PersonPhone] 
    go 
    SELECT * 
    INTO Person.BusinessEntityAddress_Test 
    FROM [Person].BusinessEntityAddress 
    go 
    SELECT * 
    INTO Person.Address_Test 
    FROM [Person].Address 
    go 

SET STATISTICS IO ON 
SET STATISTICS TIME ON 

index --create sur les tables

CREATE CLUSTERED INDEX Person1 ON Person.Person_Test (BusinessEntityID); 
CREATE CLUSTERED INDEX PersonPhone1 ON Person.PersonPhone_Test (BusinessEntityID); 
CREATE CLUSTERED INDEX BusEntity1 ON Person.BusinessEntityAddress_Test (BusinessEntityID); 
CREATE INDEX BusEntity2 ON Person.BusinessEntityAddress_Test (AddressId); 
CREATE CLUSTERED INDEX AddressInd1 ON Person.Address_Test (AddressId); 

--create une vue basée sur les quatre tables

CREATE VIEW My_View WITH SCHEMABINDING AS 
     SELECT P.BusinessEntityID,P.FirstName,P.LastName, PH.PhoneNumber,PH.PhoneNumberTypeID,BU.AddressID,AD.AddressLine1 
     FROM Person.Person_Test P 
     INNER JOIN Person.PersonPhone_Test PH 
     ON P.BusinessEntityID=PH.BusinessEntityID 
     INNER JOIN Person.BusinessEntityAddress_Test BU 
     ON P.BusinessEntityID=BU.BusinessEntityID 
     INNER JOIN Person.Address_Test AD 
     ON BU.AddressID=AD.AddressID 
     WHERE P.BusinessEntityID BETWEEN 50 AND 10000 AND AD.AddressID BETWEEN 100 AND 1000 
    GO 

Puis-je tester le performance sans index (Query1)

--Test regular view 
SELECT BusinessEntityID,LastName,PhoneNumber,AddressID, AddressLine1 
FROM My_View 
WHERE BusinessEntityID between 50 and 200 

Le message que je suis arrivé est:

SQL Server parse and compile time: 
    CPU time = 0 ms, elapsed time = 8 ms. 
SQL Server parse and compile time: 
    CPU time = 0 ms, elapsed time = 0 ms. 

(91 row(s) affected) 
Table 'Address_Test'. Scan count 91, logical reads 185, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'PersonPhone_Test'. Scan count 91, logical reads 184, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'Person_Test'. Scan count 91, logical reads 286, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'BusinessEntityAddress_Test'. Scan count 1, logical reads 3, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 

SQL Server Execution Times: 
    CPU time = 0 ms, elapsed time = 1 ms. 

Puis-je ajouter index sur la vue

CREATE UNIQUE CLUSTERED INDEX idx_MyView ON My_View(BusinessEntityID); 
go 

Cependant, je suis le même message si j'exécutez à nouveau la requête ci-dessus 1. Je joins également le plan d'exécution ici. Les deux plans d'exécution sont identiques, quelle que soit la vue indexée ou non indexée. enter image description hereenter image description here

Y at-il quelque chose que j'ai raté? Pourquoi la performance est la même après que j'ajoute l'index à la vue?

+1

Je dis déposer les index sur la table et refaire le test. Dans votre plan, toutes les opérations utilisent index_seek. Si SQL utilise des index sur des tables, cela n'a pas d'importance si vous avez un index en vue ou non. rappelez-vous que l'optimiseur est très intelligent.De toute façon, vous pouvez obtenir une meilleure réponse si vous postez sur le site dba. http://dba.stackexchange.com – FLICKER

+0

Quelle version os sql-server? Standard ou Entreprise? Envisagez d'exécuter la requête sur la vue avec le queryhint NOEXPAND. – mxix

+0

@mxix Vous avez raison. NOEXPAND me donne un autre message. – NewGuyComesIn

Répondre

2

La condition de vue est plus restrictive que la condition de requête. La vue a moins de données que nécessaire.

WHERE P.BusinessEntityID BETWEEN 50 AND 10000 AND AD.AddressID BETWEEN 100 AND 1000 

contre

WHERE BusinessEntityID between 50 and 200 

Même qui est mise en correspondance fixe vue indexée est très fragile et peut échouer. Vous devrez peut-être forcer en utilisant NOEXPAND.

+0

Merci pour l'explication. – NewGuyComesIn

1

Merci à @mxix. NOEXPAND me donne un nouveau message.

SELECT BusinessEntityID,LastName,PhoneNumber,AddressID, AddressLine1 
FROM My_View WITH (NOEXPAND) 
WHERE BusinessEntityID between 50 and 200; 
go 

Le message:

SQL Server parse and compile time: 
     CPU time = 0 ms, elapsed time = 0 ms. 
    SQL Server parse and compile time: 
     CPU time = 0 ms, elapsed time = 0 ms. 

(91 row(s) affected) 
Table 'My_View'. Scan count 1, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 

SQL Server Execution Times: 
    CPU time = 0 ms, elapsed time = 0 ms. 

enter image description here @FLICKER est aussi juste que optimiseur est très intelligent.


@usr souligne le point clé. Si j'utilise

SELECT BusinessEntityID,LastName,PhoneNumber,AddressID, AddressLine1 
FROM My_View 
WHERE BusinessEntityID between 100 and 20000; 
go 

Je n'ai pas besoin de spécifier NOEXPAND. SQL Server utilisera l'index dans la vue automatiquement.

SQL Server parse and compile time: 
    CPU time = 15 ms, elapsed time = 16 ms. 
SQL Server parse and compile time: 
    CPU time = 0 ms, elapsed time = 0 ms. 

(129 row(s) affected) 
Table 'My_View'. Scan count 1, logical reads 5, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 

SQL Server Execution Times: 
    CPU time = 0 ms, elapsed time = 0 ms. 
+0

Ce n'est pas une requête différente avec différents ensembles de filtres. – usr