sélectionnez * vs sélectionner la colonne
Si j'ai juste besoin de 2/3 des colonnes et j'ai une requête SELECT *
au lieu de fournir ces colonnes dans la requête de sélection, est-il une dégradation des performances en ce qui concerne plus/moins d'e/S ou de mémoire?
La surcharge du réseau peut être présent si je ne sélectionnez * sans nécessité.
Mais dans une opération de sélection, le moteur de base de données toujours tirer atomique tuple à partir du disque, ou faut-il tirer uniquement les colonnes demandées dans l'opération de sélection?
Si il tire toujours un tuple puis-je/O surcharge est la même.
Dans le même temps, il y a peut être une consommation de mémoire pour décaper les colonnes de la n-uplet, si elle tire un n-uplet.
Si c'est le cas, sélectionnez someColumn aura plus de surcharge de mémoire que celle de select *
- Est-il un SGBDR spécifique vous vous posez à propos de? Il est possible que la façon dont
SELECT
les requêtes sont exécutées/de traitement est différente de la base de données de la base de données. - En aparté, dans PostgreSQL, si vous dites
CREATE VIEW foo_view AS SELECT * FROM foo;
, puis ajouter des colonnes à la table foo plus tard, ces colonnes ne s'affichent automatiquement dans la foo_view comme prévu. En d'autres termes, la*
dans ce contexte se développe seulement une fois (lors de la création de la vue de temps), pas pour le SÉLECTIONNER. En raison de complications découlant de l'ALTER TABLE, je dirais que (dans la pratique)*
est Considéré comme Nocif. - pas seulement PostgresQL, c'est aussi le comportement de l'Oracle.
- double possible de les Meilleurs à utiliser * lors de l'appel de beaucoup de champs dans mysql?
- Poneys: je n'étais pas au courant de la poste similaire. Toutefois, Ces méthodes ne sont pas vraiment similer. @Lèse-majesté: je parle Générique SGBDR. pas à propos de tout fournisseur spécifique @Joey Adams: Hmm je sais que * est dangereux. envie de discuter des problèmes de performance concernant.
- Pour SQL Server, voir sqlblog.com/blogs/aaron_bertrand/archive/2009/10/10/...
- double possible de Pourquoi est-SELECT * considéré comme nocif?
- pas seulement PostreSQL et Oracle, aussi dans Microsoft SQL
Vous devez vous connecter pour publier un commentaire.
Il tire toujours un n-uplet (sauf dans les cas où le tableau a été verticalement segmenté - divisé en colonnes pièces), donc pour répondre à la question que vous avez posée, il n'a pas d'importance du point de vue des performances. Toutefois, pour de nombreuses autres raisons, (ci-dessous), vous devez toujours sélectionner spécifiquement les colonnes que vous voulez, par nom.
Il tire toujours un tuple, parce que, dans tous les vendeurs de SGBDR, je suis familier avec), le sous-jacent de stockage sur disque de la structure pour tout (y compris les données de la table) est basé sur définis I/O Pages (dans SQL Server, par exemple, chaque Page est de 8 kilo-octets). Et tous les I/O de lecture ou d'écriture est en Page.. I. e., chaque écriture ou de la lecture est une Page complète de données.
En raison de cette contrainte structurelle, une conséquence est que Chaque ligne de données dans une base de données doit toujours être sur une et une seule page. Il ne peut pas s'étendre sur plusieurs Pages de données (sauf pour certaines choses comme les gouttes, où le blob données sont stockées dans une Page séparée-morceaux, et de la ligne de la table de la colonne puis obtient seulement un pointeur...). Mais ces exceptions ne sont que des exceptions, et en général ne s'applique pas, sauf dans des cas particuliers ( pour certains types de données, ou de certaines optimisations pour des circonstances spéciales)
Même dans ces cas particuliers, en général, la ligne de la table de données elle-même (qui contient le pointeur vers les données réelles pour la Goutte, ou quoi que ce soit), il doit être stocké sur un seul IO Page...
EXCEPTION. Le seul endroit où
Select *
est OK, est dans la sous-requête après unExists
ouNot Exists
prédicat de la clause, comme dans:EDIT: Pour l'adresse @Mike Sherer commentaire, Oui c'est vrai, à la fois techniquement, avec un peu de définition pour votre cas particulier, et esthétiquement. Tout d'abord, même lorsque l'ensemble des colonnes demandées sont un sous-ensemble de ceux qui sont stockés dans certains index, le processeur de requête doit aller la chercher chaque colonne stockées dans l'indice, et pas seulement ceux demandés, pour les mêmes raisons - TOUTES les I/O doit être fait dans les pages, et les données d'index est stocké dans IO Pages tout comme les données de la table. Donc, si vous définissez "tuple" pour une page d'index comme l'ensemble des colonnes stockées dans l'index, l'instruction est toujours vrai.
et l'énoncé est vrai esthétiquement, car le point est qu'il récupère des données basées sur ce qui est stocké dans le I/O de la page, pas sur ce que vous demandez, et ce vrai si vous êtes accédant à la base de la table I/O Page ou d'un indice I/O Page.
Pour d'autres raisons de ne pas utiliser
Select *
, voir Pourquoi estSELECT *
considéré comme dangereux? :select *
aura moins de surcharge de la mémoire deselect column
mais même I/O frais généraux. donc, Si nous laissons la surcharge du réseau.select *
si moins de frais généraux que celui deselect column
select ColumnName
il y aura une surcharge de la mémoire de décapage pas demandé les Cellules de la n-uplet et de transmettre uniquement les Colonnes demandées. d'accord ?Select *
, alors, le moins de colonnes, plus le traitement... Mais encore une fois, c'est insginificant en mémoire du processeur de traitement de la charge, de manière beaucoup plus important, ce sont les potentiels de maintenance erreurs de logique et de l'utilisation deSelect *
NE PAS Utiliser pour des raisons de performances..Il y a plusieurs raisons pour lesquelles vous ne devriez jamais (jamais jamais) utilisation
SELECT *
dans le code de production:puisque vous ne donnez pas votre base de données toutes les indications sur ce que vous voulez, il faudra d'abord vérifier le tableau de définition afin de déterminer les colonnes de cette table. Cette recherche va coûter un peu de temps - pas beaucoup en une seule requête, mais il ajoute au fil du temps
si vous avez besoin seulement les 2/3 des colonnes, vous êtes en sélectionnant 1/3 de trop de données qui doit être de la récupération à partir de disques et de les envoyer sur le réseau
si vous commencez à appuyer sur certains aspects de les données, par exemple, l'ordre des colonnes retournées, vous pourriez avoir une mauvaise surprise une fois que la table est réorganisé et nouvelles colonnes sont ajoutées (ou existants supprimé)
dans SQL Server (pas sûr sur d'autres bases de données), si vous avez besoin d'un sous-ensemble de colonnes, il y a toujours une chance un index non-cluster peut être couvrant la demande contient toutes les colonnes nécessaires). Avec un
SELECT *
, vous êtes renoncer à cette possibilité en droit de l'obtenir-aller. Dans ce cas particulier, les données sont récupérées à partir de la page d'index (si ceux-ci contiennent toutes les colonnes) et donc I/O disque et surcharge de la mémoire serait beaucoup moins par rapport à faire unSELECT *....
requête.Oui, il faut un peu plus de taper dans un premier temps (des outils comme Invite SQL pour SQL Server va même vous aider, il ya) - mais c'est vraiment un cas où il y a une règle sans exception: ne jamais utiliser SELECT * dans votre code de production. JAMAIS.
select *
aura plus la surcharge du réseau. selon votre deuxième point. que vous vouliez sélectionner l'opération ne tirez pas atomique des n-uplets. plutôt, il tire seulement les colonnes demandées à partir des disques. donc, il y aura une surcharge de la mémoire dansselect column
pour vérifier les cellules de données pour tirer. que je sache les Données sont toujours stockées sur le disque comme des n-uplets. vous ne savez pas comment sélectionner le tire. doncselect *
aura pas besoin d'un enregistrement par le biais de la Structure de Données de la TableWhere Exists (Select * From ...
) l'utilisation deSelect *
est certainement pas de problème, et dans certains milieux, est considéré comme une meilleure pratique.IF EXISTS(SELECT *...
est un cas particulier - depuis, aucune donnée n'est vraiment récupéré, mais c'est juste une vérification d'existence, le SELECT * n'est pas un problème là...Vous devriez toujours seulement
select
les colonnes que vous avez réellement besoin. Il n'est jamais moins efficace pour sélectionner moins au lieu de plus, et vous aussi courir en moins d'effets secondaires inattendus - comme un accès à vos résultats les colonnes sur le côté client par l'index, puis d'avoir ces indices sont incorrectes par l'ajout d'une nouvelle colonne à la table.[edit]: Signifie l'accès. Stupide cerveau encore de se réveiller.
SELECT *
avec elle.Sauf si vous êtes le stockage de grosses gouttes, la performance n'est pas un sujet de préoccupation. La grande raison de ne pas utiliser SELECT * est que si vous êtes à l'aide de lignes renvoyées comme des n-uplets, les colonnes revenir dans l'ordre que le schéma qui se passe à spécifier, et si cela change, vous aurez à résoudre tous vos code.
D'autre part, si vous utilisez le style de dictionnaire accès alors qu'il n'a pas d'importance quel ordre les colonnes de revenir parce que vous êtes toujours y accéder par le nom.
Immédiatement me fait penser à un tableau que j'utilisais qui contient une colonne de type
blob
; il comportaient généralement une image JPEG, un peu deMb
s dans la taille.Inutile de dire que je n'ai pas
SELECT
cette colonne, à moins que je vraiment besoin. Avoir que les données flottant autour - surtout lorsque j'ai sélectionné plusieurs lignes - était juste une dispute.Cependant, j'avoue que j'généralement requête pour toutes les colonnes d'une table.
*
- j'ai fait la liste des colonnes?Lors d'un select SQL, la DB est toujours de consulter les métadonnées de la table, qu'il s'agisse d'SÉLECTIONNEZ * pour SÉLECTIONNER a, b, c... Pourquoi? Parce que c'est là que l'information sur la structure et l'agencement de la table sur le système.
Il y a qu'à lire cette information pour deux raisons. L'un, tout simplement de compiler la déclaration. Il doit assurez-vous de spécifier une table existante, à tout le moins. Aussi, la structure de base de données peuvent avoir changé depuis la dernière fois qu'une instruction a été exécutée.
Maintenant, évidemment, DB métadonnées sont mises en cache dans le système, mais il est toujours en cours de traitement qui doit être fait.
Prochain, les métadonnées sont utilisées pour générer le plan de requête. Cela se produit chaque fois qu'une instruction est compilé en tant que bien. Encore une fois, cela va à l'encontre de mise en cache de métadonnées, mais c'est toujours fait.
Le seul moment où ce traitement n'est pas fait, c'est quand la bd est à l'aide d'un pré-compilés de la requête, ou a mis en cache une requête précédente. C'est l'argument pour l'utilisation de paramètres de liaison plutôt que de SQL littérale. "SELECT * from TABLE where key = 1" est une requête différente de "SELECT * from TABLE where key = ?" et le "1" est lié à l'appel.
DBs s'appuient fortement sur la page mise en cache pour y travailler. De nombreuses modernes DBs sont suffisamment petits pour tenir entièrement dans la mémoire (ou, peut-être devrais-je dire, mémoire moderne est assez grand pour s'adapter à de nombreux DBs). Alors votre principal coût d'e/S sur le back-end est de la journalisation et de la page de bouffées de chaleur.
Toutefois, si vous êtes toujours frapper le disque pour votre DB, l'un primaire, l'optimisation effectuée par de nombreux systèmes est de s'appuyer sur les données dans les index, plutôt que de les tables elles-mêmes.
Si vous avez:
Ensuite, si vous faites "SELECT id, nom from client where id = 1", il est très probable que vous DB va tirer de ces données à partir de l'index, plutôt que de les tables.
Pourquoi? Il faudra probablement utiliser l'index pour satisfaire à la requête (vs une analyse de la table), et même si le " nom " n'est pas utilisée dans la clause where, cet indice sera toujours la meilleure option pour la requête.
Maintenant la base de données dispose de toutes les données dont il a besoin pour satisfaire à la requête, donc il n'y a pas de raison de frapper la table des pages elles-mêmes. En utilisant les résultats de l'indice en moins de trafic sur le disque puisque vous avez une plus grande densité de lignes dans l'index vs la table en général.
C'est une main ondulé explication spécifique d'une technique d'optimisation utilisée par certaines bases de données. Beaucoup ont plusieurs optimisation et performances techniques.
En fin de compte, SÉLECTIONNEZ * est utile pour les requêtes dynamiques, vous devez taper à la main, je n'avais jamais utiliser de "vrais code". L'Identification de chaque colonne donne la DB plus d'informations qu'il peut utiliser pour optimiser la requête, et vous donne un meilleur contrôle de votre code avec les modifications de schéma, etc.
Je pense qu'il n'y a pas de réponse exacte à votre question, parce que vous devez méditer sur la performance et la facilité de maintenir vos applications.
Select column
est plus performatic deselect *
, mais si vous est le développement d'une orientée objet système, alors vous aimerez utiliserobject.properties
et vous pouvez avoir besoin d'une propriétés dans n'importe quelle partie de la liste applications, puis vous aurez besoin d'écrire plus de méthodes pour obtenir des propriétés dans des situations particulières, si vous n'utilisez passelect *
et remplir toutes les propriétés. Vos applications doivent avoir une bonne performance à l'aide deselect *
et, dans certains cas, vous devrez sélectionner la colonne pour améliorer les performances. Puis vous aurez le meilleur des deux mondes, de la facilité à écrire et maintenir des applications et des performances lorsque vous avez besoin de performance.La accepté de répondre ici est faux. Je suis tombé sur ce quand une autre question été fermé comme un duplicata de celui-ci (alors que j'étais encore écrit ma réponse - grr - d'où le SQL ci-dessous les références de l'autre question).
Vous devriez toujours utiliser SÉLECTIONNER un attribut, attribut.... PAS SELECT *
C'est principalement pour des problèmes de performances.
N'est pas un très bon exemple. Plutôt considérer:
Si il y a un index sur (nom, numéro de téléphone), puis la requête peut être résolu sans avoir à rechercher les valeurs correspondantes de la table - il y a un couvrant index.
En outre, supposons que la table a un BLOB contenant une image de l'utilisateur, et un paquet de CV, et une feuille de calcul...
à l'aide de SELECT * va willpull toute cette information dans le SGBD tampons (en forçant d'autres informations utiles à partir de la mémoire cache). Puis il sera envoyé au client à l'aide de temps sur le réseau et de la mémoire sur le client pour les données redondantes.
Il peut aussi causer des problèmes fonctionnels si le client récupère les données sous forme d'un énumérés array (tels que le PHP est mysql_fetch_array($x, MYSQL_NUM)). Peut-être que lorsque le code a été écrit 'téléphone' était la troisième colonne pour être retournée par SELECT *, mais quelqu'un arrive et décide d'ajouter une adresse de courriel à la table, placée avant 'téléphone'. Le champ est maintenant passée à la 4e colonne.
Il y a des raisons de faire les choses de toute façon. J'utilise SELECT * beaucoup sur PostgreSQL, car il y a beaucoup de choses que vous pouvez faire avec SELECT * PostgreSQL que vous ne pouvez pas faire avec une colonne explicite de la liste, en particulier lorsque des procédures stockées. De même, dans Informix, SÉLECTIONNEZ * plus hérité d'un tableau arbre peut vous donner irréguliers lignes tout en colonne explicite liste ne peut pas parce que plus de colonnes dans les tables enfants sont retournés.
La principale raison pour laquelle je fais cela dans PostgreSQL, c'est qu'il s'assure que je reçois un bien formée type spécifique à une table. Cela me permet de prendre les résultats et de les utiliser comme type de table dans PostgreSQL. Cela permet aussi de beaucoup plus d'options dans la requête qu'un rigide de la colonne de liste serait.
D'autre part, une conception rigide de la colonne de la liste vous donne un niveau de l'application, vérifier que db schémas n'ont pas changé d'une certaine façon et cela peut être utile. (Je ne ces contrôles sur un autre niveau.)
Que pour la performance, j'ai tendance à utiliser les Vues et les procédures stockées retour de types (et puis une liste de colonnes à l'intérieur de la procédure stockée). Cela me donne beaucoup de contrôle sur ce que les types sont retournés.
Mais gardez à l'esprit que je suis à l'aide de SELECT * en général, à l'encontre d'une couche d'abstraction plutôt que de tables de base.
Référence prise à partir de cet article:
Sans SELECT *:
Lorsque vous utilisez ” SELECT * ” à l'époque, vous sélectionnez plusieurs colonnes de la base de données et une partie de cette colonne peut pas être utilisé par votre application.
Cela permettra de créer de coût supplémentaire et une charge sur le système de base de données et plus voyager à travers le réseau.
Avec SELECT *:
Si vous avez des exigences particulières et créé dynamique de l'environnement lors de l'ajout ou de la suppression de la colonne de traiter automatiquement par le code de l'application. Dans ce cas spécial, vous n'avez pas besoin de changer d'application et une base de code et cela va automatiquement une incidence sur l'environnement de production. Dans ce cas, vous pouvez utiliser le bouton “SELECT *”.
Juste pour ajouter une nuance à la discussion, je ne vois pas ici: En termes d'I/O, si vous utilisez une base de données avec orientée sur la colonne de stockage vous pouvez faire BEAUCOUP moins d'e/S si vous n'requête pour certaines colonnes. Comme nous nous dirigeons vers des disques Ssd, les avantages pourraient être un peu plus petit vs ligne orientée de stockage, mais il y en a) que la lecture de blocs qui contiennent des colonnes vous vous souciez b) de compression, qui est généralement réduit considérablement la taille des données sur le disque et donc le volume de lecture de données à partir du disque.
Si vous n'êtes pas familier avec la colonne de stockage orientée, une mise en œuvre pour Postgres vient de Citus de Données, un autre est Greenplum, un autre Paraccel, l'autre (grosso modo) d'Amazon Redshift. Pour MySQL, il y a Infobright, la maintenant presque disparu InfiniDB. D'autres offres commerciales comprennent de HP Vertica, Sybase IQ, Teradata...
l'égalité des