Est-ce que ces deux CTE devraient faire la même chose?

Si nous avons une vue SQL VIEW_MYTABLE avec, disons, 50 colonnes.

Option 1 :

 with CTE_MYQUERY1 as ( select [VIEW_MYTABLE].* from [VIEW_MYTABLE] /*some complex where clause*/ ) 

Option 2 :

 with CTE_MYQUERY2 as ( select [COLUMN_1], [COLUMN_2], [COLUMN_3], ...., [COLUMN_10] from [VIEW_MYTABLE] /*some complex where clause*/ ) 

Selon ma compréhension, sélectionner avec les colonnes définies est toujours plus rapide que l'instruction select * . Notez que dans cette deuxième requête, je sélectionne seulement 10 des 50 colonnes de la vue.

Je reçois les deux résultats en tant que même? Quelqu'un peut-il également me dire comment le CTE fonctionne en interne, génère-t-il d'abord un set de résultats, puis l'envoie à la requête suivante (requête SELECT dans mon cas)?

Je ne m'attendrais absolument à aucune différence perceptible dans les time d'exécution entre ces deux requêtes.

Cependant, je préconiserais encore contre SELECT *, et non pour des raisons de performance. Il existe un mythe établi depuis longtime selon lequel SELECT * est less efficace parce que le moteur doit aller chercher les noms de colonnes dans les métadonnées, mais la vérité est qu'il existe toujours une search pour valider les noms de colonne que vous avez écrits, et le le coût supplémentaire de récupération des noms ne sera pas perceptible par les humains, quelle que soit la taille de l'set de résultats.

Les raisons que je défends contre SELECT * sont les suivantes:

  • il est peu probable que vous ayez besoin de toutes les colonnes de la table (ou de toutes les lignes, mais c'est une histoire différente). Si vous extrayez plus de colonnes que vous n'en avez besoin, vous effectuez des E / S inutiles et vous obligez peut-être SQL Server à effectuer une parsing d'index cluster / table alors qu'il aurait pu effectuer un scan sur un index beaucoup plus maigre.

  • Même si vous avez besoin de toutes les colonnes, l'utilisation de SELECT * peut entraîner des problèmes difficiles à détecter dans votre code plus tard. Que faire si quelqu'un insère une colonne au milieu de la table? Crée une colonne Ajoute une colonne? Renomme une colonne? Certains d'entre eux seront détectés immédiatement, mais j'ai démontré des cas où cela peut causer toutes sortes de problèmes difficiles à déboguer.

http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/10/bad-habits-to-kick-using-select-omitting-the-column-list.aspx


En ce qui concerne le fonctionnement général des CTE, c'est une question assez large ici. Je commencerais par ces articles:

http://www.simple-talk.com/sql/t-sql-programming/sql-server-cte-basics/

http://msdn.microsoft.com/en-us/magazine/cc163346.aspx

http://msdn.microsoft.com/en-us/library/ms190766%28v=sql.100%29.aspx

La principale façon dont SELECT * peut nuire aux performances est de faire perdre du time à la requête en récupérant beaucoup plus de données que ce qui est réellement nécessaire. Mais c'est la clause SELECT dans la partie principale de la requête qui détermine queldatatables sont récupérées. * Une expression de table commune (non récursive) peut être considérée comme une sorte de vue unique. Toutes les colonnes du CTE qui ne sont pas référencées dans la requête qui l'utilise finiront par être ignorées. Similaire à la façon dont lorsque vous effectuez une requête sur une vue, le moteur n'obtient pas nécessairement toutes les colonnes de la vue, juste chaque colonne que vous avez demandée.

Je suppose que vous obtenez la même performance avec les deux CTE parce que la requête qui les utilise, que vous avez omis dans les exemples, est identique dans les deux cas. Pour cette raison, les colonnes supplémentaires référencées dans votre première option n'ont aucune influence sur datatables récupérées par la requête complète.

* Ajouté: Pour plus de clarté, ce n'est le cas que pour SELECT . WHERE clauses WHERE et JOIN affecteront les colonnes qui doivent être lues où qu'elles apparaissent.

Ne renvoyez pas plus de colonnes ou de lignes de données au client que nécessaire. Cela augmente simplement les E / S disque sur le trafic du server et du réseau, ce qui nuit aux performances. Dans les SELECT , n'utilisez pas SELECT * pour renvoyer des lignes, spécifiez toujours dans votre SELECT quelles colonnes doivent être renvoyées pour cette requête particulière, et non plus une colonne. Dans la plupart des cas, assurez-vous d'inclure une clause WHERE pour réduire le nombre de lignes envoyées aux seules lignes dont les clients ont besoin pour exécuter la tâche immédiatement.

À mon avis, la grande différence sera sur votre clause WHERE complexe comme c'est là où les actions principales ont lieu, les index impliqués, etc.

Tout cela étant dit, je crois que la 2e fonctionnera mieux dans presque tous les scénarios.

Consultez cet article détaillé par Steve Jones sur SQL Central .