Dans SQL Server 2012 (ou toute version à partir de 2005), l'utilisation SELECT *...
n'est qu'un problème de performances possible dans l'instruction SELECT de niveau supérieur d'une requête.
Donc, ce n'est PAS un problème dans Views (*), dans les sous-requêtes, dans les clauses EXIST, dans les CTE, ni dans SELECT COUNT(*)..
etc., etc. Notez que cela est probablement également vrai pour Oracle, DB2 et peut - être PostGres (pas sûr) , mais il est très probable que cela reste un problème dans beaucoup de cas pour MySql.
Pour comprendre pourquoi (et pourquoi cela peut toujours être un problème dans un SELECT de niveau supérieur), il est utile de comprendre pourquoi il en a déjà été un, car son utilisation SELECT *..
signifie " renvoyer TOUTES les colonnes ". En général, cela renvoie beaucoup plus de données que vous ne le souhaitez vraiment, ce qui peut évidemment entraîner beaucoup plus d'E / S, à la fois sur disque et sur le réseau.
Ce qui est moins évident, c'est que cela limite également les index et les plans de requête qu'un optimiseur SQL peut utiliser, car il sait qu'il doit finalement renvoyer toutes les colonnes de données. S'il peut savoir à l'avance que vous ne voulez que certaines colonnes, il peut souvent utiliser des plans de requête plus efficaces en exploitant les index contenant uniquement ces colonnes. Heureusement, il existe un moyen de le savoir à l'avance, c'est-à-dire de spécifier explicitement les colonnes souhaitées dans la liste. Mais lorsque vous utilisez "*", vous renoncez à "tout donner, je vais trouver ce dont j'ai besoin".
Oui, chaque colonne nécessite également une utilisation accrue de la CPU et de la mémoire, mais elle est presque toujours mineure comparée à ces deux choses: la bande passante supplémentaire importante nécessaire pour le disque et la bande passante réseau requise pour les colonnes inutiles plan de requête optimisé car il doit inclure chaque colonne.
Alors qu'est-ce qui a changé? Fondamentalement, les optimiseurs SQL ont intégré avec succès une fonctionnalité appelée "Optimisation de colonne", ce qui signifie simplement qu'ils peuvent désormais déterminer dans les sous-requêtes de niveau inférieur si vous envisagez d'utiliser une colonne dans les niveaux supérieurs de la requête.
Le résultat de ceci est que cela n'a plus d'importance si vous utilisez 'SELECT * ..' dans les niveaux inférieurs / internes d'une requête. Au lieu de cela, ce qui compte vraiment, c’est ce qui est dans la liste des colonnes du SELECT de niveau supérieur. À moins que vous n'utilisiez SELECT *..
dans le haut, alors encore une fois, il faut supposer que vous voulez TOUTES les colonnes et que vous ne pouvez donc pas utiliser efficacement les optimisations de colonne.
(* - Notez qu'il existe un problème de liaison mineur et différent dans les vues, *
où elles n'enregistrent pas toujours les modifications dans les listes de colonnes lorsque "*" est utilisé. Il existe d'autres moyens de résoudre ce problème sans que cela affecte les performances.)
Il est autorisé physiquement et problématique à utiliser
select * from table
, cependant, c'est une mauvaise idée. Pourquoi?Tout d'abord, vous constaterez que vous renvoyez des colonnes dont vous n'avez pas besoin (ressources lourdes).
Deuxièmement, une table volumineuse prendra plus de temps que de nommer les colonnes car lorsque vous sélectionnez *, vous sélectionnez en fait les noms de colonne dans la base de données et vous dites "donnez-moi les données associées aux colonnes dont le nom figure dans cette autre liste. . " Bien que cela soit rapide pour le programmeur, imaginez que vous fassiez cette recherche sur l'ordinateur d'une banque qui pourrait avoir littéralement des centaines de milliers de recherches en une minute.
Troisièmement, cela rend en réalité la tâche plus difficile pour le développeur. À quelle fréquence devez-vous basculer de SSMS à VS pour obtenir tous les noms de colonnes?
Quatrièmement, c'est un signe de programmation paresseuse et je ne pense pas qu'un développeur veuille cette réputation.
la source
Cela peut poser un problème si vous insérez le
Select * ...
code dans un programme, car, comme indiqué précédemment, la base de données peut changer au fil du temps et comporter plus de colonnes que ce à quoi vous vous attendiez lorsque vous avez écrit la requête. Cela peut conduire à un échec du programme (dans le meilleur des cas) ou bien le programme risque de mal tourner et de corrompre certaines données car il examine des valeurs de champ pour lesquelles il n'a pas été écrit. En bref, le code de production doit TOUJOURS spécifier les champs à retourner dans le fichierSELECT
.Cela dit, j'ai moins de problèmes lorsque cela
Select *
fait partie d'unEXISTS
article, car tout ce qui va être renvoyé au programme est un booléen indiquant le succès ou l'échec du choix. D'autres peuvent être en désaccord avec cette position et je respecte leur opinion à ce sujet. Il PEUT être légèrement moins efficace de coderSelect *
que de coder "Select 1" dans uneEXISTS
clause, mais je ne pense pas qu'il y ait de risque de corruption des données, de toute façon.la source
Il y a beaucoup de réponses à cela
select *
, alors je couvrirai quand j'estime que c'est bien ou du moins que c'est OK.1) Dans un EXISTS, le contenu de la partie SELECT de la requête est ignoré. Vous pouvez donc écrire
SELECT 1/0
et éviter les erreurs.EXISTS
vérifie simplement que certaines données renverraient et renvoie un booléen basé sur cela.2) Cela pourrait déclencher une tempête de feu, mais j'aime utiliser les
select *
déclencheurs de ma table d'historique. Parselect *
, il empêche la table principale d’obtenir une nouvelle colonne sans l’ajouter à la table historique, car elle est immédiatement erronée lorsqu’elle est insérée / mise à jour / supprimée dans la table principale. Cela a empêché de nombreuses fois les développeurs d’ajouter des colonnes et d’oublier de l’ajouter à la table de l’historique.la source
SELECT 1
parce que cela indique très clairement aux futurs responsables de la maintenance du code votre intention. Ce n'est pas une obligation , mais si je le vois,... WHERE EXISTS (SELECT 1 ...)
cela s'annonce évidemment comme un test de vérité.SELECT 1
un mythe selon lequel les performances seraient meilleures queSELECT *
. Cependant, les deux options sont parfaitement acceptables. Il n’ya pas de différence de performances en raison de la manière dont optimser traite les EXISTS. Ni aucune différence de lisibilité à cause du mot "EXISTS" qui annonce clairement un test de vérité.Column8
à la table principale en oubliant la table d'historique. Developer écrit un tas de code transmis à la colonne 8. Ensuite, il ajoute des élémentsColumn9
à la table principale. cette fois en rappelant d'ajouter également à l'histoire. Plus tard, lors des tests, il réalise qu’il a oublié d’ajouterColumn9
à l’historique (grâce à votre technique de détection des erreurs) et l’ajoute rapidement. Maintenant, le déclencheur semble fonctionner, mais les données des colonnes 8 et 9 sont mélangées dans l'historique. : S