J'ai entendu dire que SELECT *
c'est généralement une mauvaise pratique à utiliser lors de l'écriture de commandes SQL, car elle est plus efficace pour les SELECT
colonnes dont vous avez spécifiquement besoin.
Si j'ai besoin de SELECT
chaque colonne d'une table, dois-je utiliser
SELECT * FROM TABLE
ou
SELECT column1, colum2, column3, etc. FROM TABLE
L'efficacité compte-t-elle vraiment dans ce cas? Je pense que ce SELECT *
serait plus optimal en interne si vous avez vraiment besoin de toutes les données, mais je dis cela sans réelle compréhension de la base de données.
Je suis curieux de savoir quelle est la meilleure pratique dans ce cas.
MISE À JOUR: Je devrais probablement préciser que la seule situation où je vraiment envie de faire unSELECT *
est quand je sélectionne des données d'une table où je sais que toutes les colonnes auront toujours besoin d' être récupérées, même lorsque de nouvelles colonnes sont ajoutées.
Compte tenu des réponses que j'ai vues cependant, cela semble toujours être une mauvaise idée et SELECT *
ne devrait jamais être utilisé pour des raisons beaucoup plus techniques auxquelles j'ai jamais pensé.
Réponses:
L'une des raisons pour lesquelles la sélection de colonnes spécifiques est préférable est qu'elle augmente la probabilité que SQL Server puisse accéder aux données à partir d'index plutôt que d'interroger les données de la table.
Voici un article que j'ai écrit à ce sujet: La vraie raison pour laquelle les requêtes de sélection sont une mauvaise couverture d'index
Il est également moins fragile de changer, car tout code qui consomme les données obtiendra la même structure de données quelles que soient les modifications que vous apporterez au schéma de table à l'avenir.
la source
vs
all_column_names) alors que nous avons des milliers de lignes et que nous effectuons SELECT avec index (dans la clause WHERE) ??Compte tenu de votre cahier des charges que vous êtes sélectionnez toutes les colonnes, il y a peu de différence à ce moment . Sachez cependant que les schémas de base de données changent. Si vous utilisez,
SELECT *
vous allez ajouter de nouvelles colonnes à la table, même si selon toute vraisemblance, votre code n'est pas prêt à utiliser ou à présenter ces nouvelles données. Cela signifie que vous exposez votre système à des changements de performances et de fonctionnalités inattendus.Vous voudrez peut-être rejeter cela comme un coût mineur, mais sachez que les colonnes dont vous n'avez pas besoin doivent toujours être:
L'élément n ° 1 a de nombreux coûts cachés, y compris l'élimination de certains index de couverture potentiels, provoquant des chargements de pages de données (et la destruction du cache du serveur), entraînant des verrous de ligne / page / table qui pourraient être évités autrement.
Comparez cela aux économies potentielles de la spécification des colonnes par rapport à an
*
et les seules économies potentielles sont:Pour l'élément 1, la réalité est que vous allez ajouter / modifier du code pour utiliser toute nouvelle colonne que vous pourriez ajouter de toute façon, donc c'est un lavage.
Pour l'élément 2, la différence est rarement suffisante pour vous pousser dans une taille de paquet ou un nombre de paquets réseau différents. Si vous arrivez au point où le temps de transmission des instructions SQL est le problème prédominant, vous devez probablement d'abord réduire le taux d'instructions.
Pour l'élément 3, il n'y a AUCUNE économie car l'expansion du
*
doit se produire de toute façon, ce qui signifie de toute façon consulter le schéma des tables. De manière réaliste, la liste des colonnes entraînera le même coût car elles doivent être validées par rapport au schéma. En d'autres termes, c'est un lavage complet.Pour l'élément 4, lorsque vous spécifiez des colonnes spécifiques, le cache de votre plan de requête peut devenir plus volumineux, mais uniquement si vous avez affaire à différents ensembles de colonnes (ce qui n'est pas ce que vous avez spécifié). Dans ce cas, vous voulez des entrées de cache différentes car vous voulez des plans différents selon vos besoins.
Donc, tout cela se résume, en raison de la façon dont vous avez spécifié la question, au problème de résilience face à d'éventuelles modifications de schéma. Si vous gravez ce schéma dans la ROM (cela arrive), alors un
*
est parfaitement acceptable.Cependant, ma directive générale est que vous ne devez sélectionner que les colonnes dont vous avez besoin, ce qui signifie que parfois il semblera que vous les demandiez toutes, mais les DBA et l'évolution du schéma signifient que de nouvelles colonnes peuvent apparaître, ce qui pourrait grandement affecter la requête. .
Mon conseil est que vous devez TOUJOURS CHOISIR des colonnes spécifiques . N'oubliez pas que vous devenez bon dans ce que vous faites encore et encore, alors prenez l'habitude de le faire correctement.
Si vous vous demandez pourquoi un schéma peut changer sans changement de code, pensez à la journalisation d'audit, aux dates d'effet / d'expiration et à d'autres éléments similaires qui sont ajoutés par les administrateurs de base de données pour des problèmes de conformité systématiques. Une autre source de changements sournois est la dénormalisation des performances ailleurs dans le système ou dans les champs définis par l'utilisateur.
la source
Vous ne devez sélectionner que les colonnes dont vous avez besoin. Même si vous avez besoin de toutes les colonnes, il est toujours préférable de répertorier les noms de colonnes afin que le serveur SQL n'ait pas à interroger la table système pour les colonnes.
En outre, votre application peut être interrompue si quelqu'un ajoute des colonnes à la table. Votre programme recevra également des colonnes auxquelles il ne s'attendait pas et il ne saura peut-être pas comment les traiter.
En dehors de cela, si la table a une colonne binaire, la requête sera beaucoup plus lente et utilisera plus de ressources réseau.
la source
Il y a quatre grandes raisons pour lesquelles c'est
select *
une mauvaise chose:La raison pratique la plus importante est qu'elle oblige l'utilisateur à connaître par magie l'ordre dans lequel les colonnes seront renvoyées. Il vaut mieux être explicite, ce qui vous protège également contre le changement de table, qui s'enchaîne bien en ...
Si un nom de colonne que vous utilisez change, il est préférable de l'attraper tôt (au moment de l'appel SQL) plutôt que lorsque vous essayez d'utiliser la colonne qui n'existe plus (ou dont le nom a été changé, etc. )
La liste des noms de colonnes rend votre code beaucoup plus auto-documenté, et donc probablement plus lisible.
Si vous transférez sur un réseau (ou même si vous ne l'êtes pas), les colonnes dont vous n'avez pas besoin ne sont que du gaspillage.
la source
*
en un ensemble de noms.)Spécifier la liste de colonnes est généralement la meilleure option car votre application ne sera pas affectée si quelqu'un ajoute / insère une colonne dans la table.
la source
La spécification des noms de colonne est nettement plus rapide - pour le serveur. Mais si
alors vous feriez mieux de vous en tenir à SELECT *. Dans notre cadre, une utilisation intensive de SELECT * nous permet d'introduire un nouveau champ de contenu géré de site Web dans une table, lui donnant tous les avantages du CMS (versionnage, workflow / approbations, etc.), tout en touchant uniquement le code à un quelques points, au lieu de quelques dizaines de points.
Je sais que les gourous de la DB vont me détester pour cela - allez-y, votez-moi - mais dans mon monde, le temps des développeurs est rare et les cycles de processeur sont abondants, donc j'ajuste en conséquence ce que je conserve et ce que je gaspille.
la source
SELECT * est une mauvaise pratique même si la requête n'est pas envoyée sur un réseau.
Bien sûr, tout cela n'a pas beaucoup d'importance pour un système petit et simple.
la source
En termes de performances, SELECT avec des colonnes spécifiques peut être plus rapide (pas besoin de lire toutes les données). Si votre requête utilise vraiment TOUTES les colonnes, SELECT avec des paramètres explicites est toujours préféré. Toute différence de vitesse sera fondamentalement imperceptible et quasi constante. Un jour, votre schéma changera, et c'est une bonne assurance pour éviter les problèmes dus à cela.
la source
Beaucoup de bonnes raisons ont répondu ici jusqu'à présent, en voici une autre qui n'a pas été mentionnée.
Nommer explicitement les colonnes vous aidera avec la maintenance sur la route. À un moment donné, vous allez apporter des modifications ou effectuer un dépannage, et vous vous demandez «où diable cette colonne est-elle utilisée».
Si vous avez les noms répertoriés explicitement, alors trouver chaque référence à cette colonne - à travers toutes vos procédures stockées, vues, etc. - est simple. Videz simplement un script CREATE pour votre schéma de base de données et effectuez une recherche textuelle dans celui-ci.
la source
définissant définitivement les colonnes, car SQL Server n'aura pas à effectuer une recherche sur les colonnes pour les extraire. Si vous définissez les colonnes, SQL peut ignorer cette étape.
la source
Il est toujours préférable de spécifier les colonnes dont vous avez besoin, si vous y pensez une fois, SQL n'a pas à penser "wtf is *" à chaque fois que vous interrogez. En plus de cela, quelqu'un plus tard peut ajouter des colonnes à la table dont vous n'avez en fait pas besoin dans votre requête et vous serez mieux dans ce cas en spécifiant toutes vos colonnes.
la source
Le problème avec "select *" est la possibilité d'apporter des données dont vous n'avez pas vraiment besoin. Pendant la requête de base de données réelle, les colonnes sélectionnées n'ajoutent pas vraiment au calcul. Ce qui est vraiment «lourd», c'est le transport des données vers votre client, et toute colonne dont vous n'avez pas vraiment besoin gaspille simplement la bande passante du réseau et ajoute au temps que vous attendez que votre requête soit renvoyée.
Même si vous utilisez toutes les colonnes provenant d'un "select * ...", c'est juste pour le moment. Si à l'avenir vous modifiez la disposition de la table / vue et ajoutez plus de colonnes, vous commencerez à les intégrer dans vos sélections même si vous n'en avez pas besoin.
Un autre point dans lequel une instruction "select *" est mauvaise est la création de la vue. Si vous créez une vue à l'aide de "select *" et que vous ajoutez ultérieurement des colonnes à votre table, la définition de la vue et les données renvoyées ne correspondent pas, et vous devrez recompiler vos vues pour qu'elles fonctionnent à nouveau.
Je sais qu'écrire un "select *" est tentant, car je n'aime vraiment pas spécifier manuellement tous les champs de mes requêtes, mais lorsque votre système commencera à évoluer, vous verrez que cela vaut la peine de passer ce temps supplémentaire / effort pour spécifier les champs plutôt que de passer beaucoup plus de temps et d'efforts à supprimer les bogues sur vos vues ou à optimiser votre application.
la source
Bien que lister explicitement les colonnes soit bon pour les performances, ne soyez pas fou.
Donc, si vous utilisez toutes les données, essayez SELECT * pour plus de simplicité (imaginez avoir de nombreuses colonnes et faire une requête JOIN ... peut devenir horrible). Ensuite - mesurez. Comparez avec la requête avec les noms de colonne répertoriés explicitement.
Ne spéculez pas sur les performances, mesurez-les!
La liste explicite est plus utile lorsque vous avez une colonne contenant des données volumineuses (comme le corps d'un article ou d'un article) et que vous n'en avez pas besoin dans une requête donnée. Ensuite, en ne le renvoyant pas dans votre serveur de base de données de réponse, vous pouvez gagner du temps, de la bande passante et du débit du disque. Le résultat de votre requête sera également plus petit, ce qui convient à tout cache de requête.
la source
Vous devriez vraiment sélectionner uniquement les champs dont vous avez besoin, et uniquement le nombre requis, c'est-à-dire
En dehors de la base de données, les requêtes dynamiques courent le risque d'attaques par injection et de données mal formées. En général, vous contournez cela à l'aide de procédures stockées ou de requêtes paramétrées. De plus (bien que ce ne soit pas vraiment un problème), le serveur doit générer un plan d'exécution chaque fois qu'une requête dynamique est exécutée.
la source
Select est tout aussi efficace (en termes de vitesse) si vous utilisez * ou des colonnes.
La différence concerne la mémoire, pas la vitesse. Lorsque vous sélectionnez plusieurs colonnes, SQL Server doit allouer de l'espace mémoire pour vous servir la requête, y compris toutes les données de toutes les colonnes que vous avez demandées, même si vous n'utilisez qu'une seule d'entre elles.
Ce qui compte en termes de performances, c'est le plan d'exécution qui à son tour dépend fortement de votre clause WHERE et du nombre de JOIN, OUTER JOIN, etc ...
Pour votre question, utilisez simplement SELECT *. Si vous avez besoin de toutes les colonnes, il n'y a pas de différence de performances.
la source
Il n'est PAS plus rapide d'utiliser des noms de champs explicites par rapport à *, si et seulement si, vous avez besoin d'obtenir les données pour tous les champs.
Votre logiciel client ne devrait pas dépendre de l'ordre des champs renvoyés, c'est donc aussi un non-sens.
Et il est possible (bien que peu probable) que vous ayez besoin d'obtenir tous les champs en utilisant * parce que vous ne savez pas encore quels champs existent (pensez à une structure de base de données très dynamique).
Un autre inconvénient de l'utilisation de noms de champs explicites est que s'ils sont nombreux et longs, la lecture du code et / ou du journal des requêtes est plus difficile.
La règle devrait donc être la suivante: si vous avez besoin de tous les champs, utilisez *, si vous n'avez besoin que d'un sous-ensemble, nommez-les explicitement.
la source
Le résultat est trop énorme. Il est lent à générer et envoyer le résultat du moteur SQL au client.
Le côté client, étant un environnement de programmation générique, n'est pas et ne doit pas être conçu pour filtrer et traiter les résultats (par exemple la clause WHERE, la clause ORDER), car le nombre de lignes peut être énorme (par exemple des dizaines de millions de lignes).
la source
Nommer chaque colonne que vous prévoyez d'obtenir dans votre application garantit également que votre application ne se cassera pas si quelqu'un modifie la table, tant que vos colonnes sont toujours présentes (dans n'importe quel ordre).
la source
Cela dépend de la version de votre serveur DB, mais les versions modernes de SQL peuvent mettre en cache le plan dans les deux cas. Je dirais que ce qui est le plus maintenable avec votre code d'accès aux données.
la source
Une des raisons pour lesquelles il est préférable de préciser exactement quelles colonnes vous voulez est en raison de possibles changements futurs dans la structure du tableau.
Si vous lisez manuellement des données en utilisant une approche basée sur un index pour remplir une structure de données avec les résultats de votre requête, alors à l'avenir, lorsque vous ajoutez / supprimez une colonne, vous aurez des maux de tête en essayant de comprendre ce qui n'a pas fonctionné.
Quant à ce qui est plus rapide, je m'en remettrai à d'autres pour leur expertise.
la source
Comme pour la plupart des problèmes, cela dépend de ce que vous voulez réaliser. Si vous souhaitez créer une grille de base de données qui autorisera toutes les colonnes de n'importe quelle table, alors "Select *" est la réponse. Cependant, si vous n'avez besoin que de certaines colonnes et que l'ajout ou la suppression de colonnes de la requête est rarement effectué, spécifiez-les individuellement.
Cela dépend également de la quantité de données que vous souhaitez transférer depuis le serveur. Si l'une des colonnes est définie comme mémo, graphique, blob, etc. et que vous n'avez pas besoin de cette colonne, vous feriez mieux de ne pas utiliser "Sélectionner *" ou vous obtiendrez un tas de données que vous n'avez pas veulent et vos performances pourraient en souffrir.
la source
Pour ajouter à ce que tout le monde a dit, si toutes les colonnes que vous sélectionnez sont incluses dans un index, votre jeu de résultats sera extrait de l'index au lieu de rechercher des données supplémentaires à partir de SQL.
la source
SELECT * est nécessaire si l'on veut obtenir des métadonnées telles que le nombre de colonnes.
la source
Ce que tout le monde a dit ci-dessus, plus:
Si vous recherchez un code maintenable lisible, faites quelque chose comme:
SELECT foo, barre FROM widgets;
est instantanément lisible et montre l'intention. Si vous passez cet appel, vous savez ce que vous récupérez. Si les widgets n'ont que des colonnes foo et bar, alors sélectionner * signifie que vous devez toujours penser à ce que vous récupérez, confirmer que l'ordre est correctement mappé, etc. Cependant, si les widgets ont plus de colonnes mais que vous n'êtes intéressé que par foo et bar, alors votre code devient désordonné lorsque vous recherchez un caractère générique et n'utilisez qu'une partie de ce qui est retourné.
la source
Et rappelez-vous que si vous avez une jointure interne par définition, vous n'avez pas besoin de toutes les colonnes car les données des colonnes de jointure sont répétées.
Ce n'est pas comme si la liste des colonnes dans le serveur SQl était difficile ou même chronophage. Vous les faites simplement glisser depuis le navigateur d'objets (vous pouvez tout obtenir en une seule fois en les faisant glisser à partir des colonnes de mots). Pour mettre un impact permanent sur les performances de votre système (parce que cela peut réduire l'utilisation des index et parce que l'envoi de données inutiles sur le réseau est coûteux) et rendre plus probable que vous ayez des problèmes inattendus lorsque la base de données change (parfois des colonnes sont ajoutées que vous ne voulez pas que l'utilisateur voie par exemple) juste pour gagner moins d'une minute de temps de développement est à courte vue et non professionnel.
la source
En termes de performances, j'ai vu des commentaires selon lesquels les deux sont égaux. mais aspect convivialité il y a des + et des -
Lorsque vous utilisez un (select *) dans une requête et si quelqu'un modifie la table et ajoute de nouveaux champs qui n'ont pas besoin pour la requête précédente, c'est une surcharge inutile. Et si le champ nouvellement ajouté est un blob ou un champ d'image ??? le temps de réponse de votre requête sera alors très lent.
D'autre part, si vous utilisez un (sélectionnez col1, col2, ..) et si la table est modifiée et ajouté de nouveaux champs et si ces champs sont nécessaires dans le jeu de résultats, vous devez toujours éditer votre requête de sélection après la modification de la table.
Mais je suggère de toujours utiliser select col1, col2, ... dans vos requêtes et de modifier la requête si la table est modifiée plus tard ...
la source
Définissez absolument les colonnes que vous souhaitez SELECT à chaque fois. Il n'y a aucune raison de ne pas le faire et l'amélioration des performances en vaut la peine.
Ils n'auraient jamais dû donner l'option "SELECT *"
la source
Si vous avez besoin de chaque colonne, utilisez simplement SELECT * mais rappelez-vous que l'ordre peut potentiellement changer, alors lorsque vous consommez les résultats, accédez-y par nom et non par index.
J'ignorerais les commentaires sur la façon dont * doit aller chercher la liste - les chances sont que l'analyse et la validation des colonnes nommées sont égales au temps de traitement sinon plus. N'optimisez pas prématurément ;-)
la source
En termes d'efficacité d'exécution, je n'ai connaissance d'aucune différence significative. Mais pour l'efficacité des programmeurs, j'écrirais les noms des champs car
la source
hé, soyez pratique. utilisez select * lors du prototypage et sélectionnez des colonnes spécifiques lors de l'implémentation et du déploiement. du point de vue du plan d'exécution, les deux sont relativement identiques sur les systèmes modernes. cependant, la sélection de colonnes spécifiques limite la quantité de données qui doivent être extraites du disque, stockées en mémoire et envoyées sur le réseau.
en fin de compte, le meilleur plan consiste à sélectionner des colonnes spécifiques.
la source