Les vues sont-elles optimisées lorsque je leur ajoute une clause WHERE?

28

Cela fait-il une différence si vous filtrez une vue à l'intérieur ou à l'extérieur de la vue?

Par exemple, y a-t-il une différence entre ces deux requêtes?

SELECT Id
FROM MyTable
WHERE SomeColumn = 1

Ou

SELECT Id
FROM MyView
WHERE SomeColumn = 1

Et MyViewest défini comme

SELECT Id, SomeColumn
FROM MyTable

Et la réponse est-elle différente si la table source se trouve sur un serveur lié?

Je demande parce que je dois interroger une grande table (lignes 44mil) deux fois à partir d'un serveur lié et obtenir un agrégat des résultats. Je veux savoir si je dois créer deux vues pour accéder aux données, une pour chaque requête, ou si je peux m'en tirer avec une seule vue et une WHEREclause.

Rachel
la source
1
pourquoi voudriez-vous même utiliser une vue si vous n'avez qu'une seule table dedans?
HLGEM
3
@HLGEM security?
JNK
2
@HLGEM La vue contient en fait plusieurs requêtes vers plusieurs bases de données sur différents serveurs, et elle les joint toutes par un UNION ALL. Il est beaucoup plus facile d'utiliser une vue que d'avoir à réécrire la requête UNION chaque fois que j'ai besoin des données.
Rachel
voir également stackoverflow.com/a/6654525/27535
gbn
1
@datagod Je garderai cela à l'esprit, merci :) Dans ce cas, il y a une application assez petite qui rassemble des données à partir d'un groupe de serveurs, exécute des calculs et crache un tas de rapports. Il a sa propre base de données parce que certains calculs sont assez gourmands en ressources, et je voulais le séparer de tout le reste.
Rachel

Réponses:

12

Vous ne devriez voir absolument aucune différence dans les plans ou les performances entre ces deux choix. Lorsque la vue est interrogée, elle est étendue à une requête sur la table de base, ce qui signifie que la même recherche ou analyse sera utilisée.

Maintenant, selon le type de données et la sélectivité de MyColumn, si vous vouliez créer un index filtré sur la table de base (lorsque vous passez à SQL Server 2008+), vous pourriez obtenir de meilleures performances, mais cela ne sera pas différent via la vue ou sans.

Aaron Bertrand
la source
3
Qu'en est-il de cette question , qui demande pourquoi une requête avec la whereclause en dehors de la vue prend autant de temps que lorsqu'elle est placée dans la vue?
Rachel
1
Si les vues ne sont pas pour la performance, elles sont juste pour la structure?
profimedica
1
Les vues indexées @profimedica peuvent être créées pour des raisons de performances (par exemple pour stocker des résultats intermédiaires comme des agrégats au lieu de les calculer au moment de l'exécution). Si une vue n'est pas matérialisée, cela peut être pour diverses raisons: DRY (jointure ou filtre commun effectué dans de nombreuses requêtes différentes), sécurité, obscurcissement, simplification du schéma.
Aaron Bertrand
5

Voici juste un petit exemple montrant qu'il ne devrait pas y avoir de différence. La base de données est la AdventureWorksbase de données.

Deux définitions de vue:

create view Person.vContactWhere
as

    select *
    from person.Contact
    where ContactID = 24

go

create view Person.vContactNoWhere
as

    select *
    from person.Contact

go

Voici la première requête, avec la WHEREclause incluse dans la définition de la vue:

select *
from person.vContactWhere

Voici le plan d'exécution:

entrez la description de l'image ici

Et la deuxième requête, avec la WHEREclause non pas dans la définition de la vue, mais dans la SELECTrequête:

select *
from person.vContactNoWhere
where ContactID = 24

Voici ce plan d'exécution:

entrez la description de l'image ici

Comme vous pouvez le voir sur ces plans d'exécution, ils sont identiques avec des résultats identiques. Je ne connais pas de situation où ce type de logique / conception produirait des résultats différents. Je serais donc prêt à dire que vous êtes en sécurité de toute façon, et que vous préférez les préférences personnelles (ou les procédures de magasin).

Thomas Stringer
la source
1
Qu'en est-il de cette question , qui demande pourquoi une requête avec la whereclause en dehors de la vue prend autant de temps que lorsqu'elle est placée dans la vue?
Rachel
1
@Rachel Je pense que gbn l'a assez bien expliqué dans son post et l'article qu'il a souligné. Je ne sais pas comment dire autrement.
Thomas Stringer
J'ai lié cela parce que dans ce cas, les plans d'exécution n'étaient pas les mêmes, ce qui est différent de ce que dit votre réponse.
Rachel
1
@Rachel Le problème dans cet exemple est une règle de transformation manquante . Il ne s'applique pas seulement aux vues mais également aux CTE et autres expressions de table. Dans le cas général, il n'est pas valide de pousser le prédicat vers le bas dans des expressions de table contenant des fonctions de classement car cela changerait le résultat. La raison pour laquelle elle est valable dans ce cas est que la Whereclause correspond à la PARTITION BY. SQL Server 2008 semble avoir une nouvelle règle SelOnSeqPrjpour reconnaître ce cas particulier.
Martin Smith
1
@Rachel - Plus d'informations sur ce problème ici
Martin Smith
2

Sur la base de ce que je lis , SQL utilisera une vue standard comme une sous-requête lors de la détermination du plan d'exécution.

Donc, en utilisant mon exemple de requête,

SELECT Id
FROM MyView
WHERE SomeColumn = 1

MyViewest défini comme

SELECT Id, SomeColumn
FROM MyTable

il doit générer le même plan d'exécution que

SELECT Id
FROM 
(
    SELECT Id, SomeColumn
    FROM MyTable
) as T
WHERE SomeColumn = 1

mais ce plan d'exécution peut être différent de ce qui serait généré avec

SELECT Id
FROM MyTable
WHERE SomeColumn = 1

Je ne sais pas si cette réponse serait la même pour les vues indexées

Rachel
la source
Je ne pense pas que ce soit un remplacement de texte explicite comme ça.
Aaron Bertrand
@AaronBertrand Vous avez peut-être raison. Honnêtement, je n'ai aucune idée ... J'apprends au fur et à mesure :) Cette hypothèse était basée sur d'autres choses que j'ai lues sur la façon dont les vues sont comme des macros. J'ai légèrement modifié la question pour préciser que je fais référence à des vues standard et non à des vues indexées.
Rachel
@Rachel - La substitution se produit avec l'arbre algébriqué non à un niveau textuel.
Martin Smith
@MartinSmith Hrrmm n'est-ce pas ce que j'ai dit? Que les plans d'exécution devraient être les mêmes, pas que le texte soit le même? Je ne suis pas sûr de comprendre "arbre algébriqué"
Rachel
C'était juste en réponse à votre commentaire sur le Q lui-même qui dit qu'il "insère le texte d'une vue dans votre requête" et au commentaire d'Aaron ci-dessus. Quelques informations sur les étapes d'analyse / compilation ici . En fait, votre réponse mentionne également la substitution de texte. Que ce soit une distinction à faire. Pas certain! Mais je suppose que cela explique pourquoi il sp_refreshviewest nécessaire que le concept de substitution de texte ne le fasse pas.
Martin Smith