11
Jul/08
1

Énumérez vos champs !

On a parfois la mauvaise habitude de faire des SELECT * FROM table; Mon astuce de la semaine va tenter d’expliquer pourquoi il faudrait toujours énumérer les champs qu’on veut sélectionner, même s’il s’agit de la table au complet.

Il y a 3 raisons majeures pour lesquelles il ne faudrait JAMAIS faire de SELECT * FROM dans les requêtes d’une application:

  • La description de la table par le biais de la requête est perdue
  • Les changements de champs
  • La grosseur des champs

Description de la table

Les Q.A vont être d’accord avec moi là-dessus, il n’y a rien de mieux qu’un code avec des noms de variables et de fonctions bien choisis. Et lorsque c’est pas suffisamment explicite, les programmeurs doivent ajouter des commentaires pour aider à la compréhension du code. Les requêtes SQL ne doivent pas faire exceptions à cette règle. Supposons que vous devez fixer un bug et que vous tombez sur cette requête dans un module que vous ne connaissez pas:

SELECT * FROM users WHERE id = 1;

Simple. Tout le monde arrive à comprendre qu’est-ce que la requête fait. Mais qu’est-ce qu’on reçoit en réalité ? 1, 2, 5, 100 champs ? Quel sont leur nom et dans quel ordre on les reçoit ? On ne peut pas le savoir à moins d’avoir le schéma de la table ou de se connecter directement à la base de données pour l’obtenir.

Mais encore, on ne sait pas non plus quels champs le programmeur initial avait l’intention d’utiliser dans le reste du code. Pas moyen de figurer s’il aurait pu faire ça autrement à l’aide d’un autre champ. Peut-être qu’il a fait une faute de frappe dans le nom d’un champ.

SELECT id_officiel , nom, prenom, email, categorie FROM users WHERE id =1;

Cette requête est un peu plus longue, ok, mais elle beaucoup plus explicite. On sait avec certitude ce qu’on demande et ce qu’on reçoit. Le nom des champs forme une documentation en soit. Je peux même supposer que le champs « id » n’est pas le ID qui sera affiché à l’écran puisque la table possède un «id_officiel». Un concept impossible à apercevoir avec la première requête.

Changements de champs

Les tables changent, pour le mieux la plus part du temps. Supposons qu’on décide de renommer le champs email pour courriel, car on désire garder des noms français.

SELECT * FROM users WHERE id = 1;

Super, la requête fonctionne toujours. Mais un programmeur qui n’est pas au courant de notre modif pourrait chercher longtemps avant de trouver pourquoi les emails ne s’affichent plus. Le code PHP risque de simplement faire un notice qui passera inaperçue.

SELECT id_officiel , nom, prenom, email, categorie FROM users WHERE id =1;
#1054 - Unknown column 'email' in 'field list'

Puisqu’on spécifie exactement ce que nous désirons, MySQL est capable de nous indiquer si ce que nous lui demandons correspond toujours à son schéma de table. Avec une erreur comme celle-là, le bug va prendre 10 secondes à être fixé.

La grosseur des champs

Pourquoi sélectionner tous les champs quand nous avons besoin de seulement 3 ? Supposons qu’au fil du temps on décide d’ajouter un blob nommé “photo”, et que la grosseur moyenne de ces photos sera de 120k. Une vielle interface qui liste les users fait un SELECT * FROM users LIMIT 0,100;

Supposons aussi que les 100 premiers users ai ajouté leur photo à leur profil (rappelez-vous, c’est un nouveau feature). La vieille interface fait toujours la job, car on ne souhaite pas afficher les photos ici, mais elle devenue soudainement très lente. Si on fait le calcule, on constate que 11.72 Mo supplémentaires de données sont demandées et retournées sans qu’on en ai besoin. On pourrait croire que c’est pas si grave, le serveur Web est sur le même réseau local que le serveur MySQL. Mais lorsqu’on pense que le bottleneck d’une base de données est souvent le Disque IO, qu’on lui demande 11.72 Mo de données inutiles, qu’on met ces données en RAM (la RAM est souvent une ressource assez limitée), on se rend compte que c’est pas une si bonne idée. Supposons encore que durant une période de rush, 25 personnes demandent d’afficher la page simultanément. 25 X 11.72 = 293 Mo de données à transférer pour aucune raison. Même sur un réseau local ça peut être long.

En conclusion, prenez les 20 secondes que ça prend de plus à énumérer les champs que vous voulez sélectionner!

Traduit et inspiré par piazza_milshake

Tagged as:
Comments (1) Trackbacks (0)
  1. Lubbykko
    8:20 am on October 27th, 2008

    Good site! Interesting information.. )

Leave a comment

No trackbacks yet.