Considérons un tableau de valeurs et de hachages, comme ceci:
+------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+----------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| val | char(9) | NO | | NULL | |
| val_hashed | char(50) | YES | | NULL | |
+------------+----------+------+-----+---------+----------------+
La requête suivante se termine en 0,00 secondes:
SELECT * FROM hashes ORDER BY 1 DESC LIMIT 1;
Cependant, cette requête prend 3 min 17 secondes:
SELECT val FROM hashes ORDER BY 1 DESC LIMIT 1;
Je vois que pendant que la requête est en cours d'exécution, la liste des processus l'affiche comme état Sorting result
. La situation est parfaitement reproductible. Notez qu'un autre processus effectue des INSERT
opérations sur la table en continu.
Pourquoi la requête plus spécifique prendrait-elle plus de temps à s'exécuter que la *
requête? J'ai toujours pensé que les *
requêtes devaient être évitées spécifiquement pour des raisons de performances.
mysql
performance
select
dotancohen
la source
la source
id
pour trouver la première ligne. Le second doit trier le résultat complet dans laval
colonne (non indexée) .ORDER BY NUMBER
syntaxe est assez sujette aux erreurs.SELECT *
combiné avec un index de colonne dansORDER BY
est obscurcissant quelle colonne est triée - une autre raison d'éviter*
s ...*
n'est pas explicite. Donc dire "donnez-moi toutes les colonnes et triez par la troisième" est à peu près aussi déterministe que dire "allez au supermarché et dites-moi combien de feux vous avez passés"Réponses:
La phrase
ORDER BY 1
fait référence à différentes colonnes; dans le premier, ce seraid
dans le secondval
. Puisqueid
c'est la clé, elle sera indexée etorder by
sera une quantité de travail insignifiante. Pourorder by val
, cependant, le système devra récupérer chaque ligne, trier le tableau complet parval
, puis choisir une seule de ces lignes.Changez les deux requêtes en
order by id
et je pense que vos temps d'exécution seront presque identiques.la source
La différence de performances dans votre requête est bien expliquée par MG. Je vais aborder ceci:
select *
ne comporte pas de sanctions particulières en soi, il est problématique lorsqu'il est mal utilisé. Dans une requête à table unique, cela fonctionne très bien. joignez maintenant cette table à une autre avec 20 colonnes, puis ajoutez des jointures à 5 autres tables avec plusieurs colonnes chacune. MAINTENANT, c'est un problème. Il en va de même pour les personnes qui enseignent un large pansement "ne faites jamais X" sans expliquer pourquoi.la source
SELECT *
peut être un problème même pour une requête à table unique. Par exemple,SELECT * FROM hashes ORDER BY val;
fera probablement une analyse complète de la table, puis un tri tandis queSELECT val FROM hashes ORDER BY val;
ne fera qu'une analyse complète de l'index, et aucun tri (en supposant qu'un index existe sur val). Ainsi, cela ne fait jamais de mal de ne sélectionner que les résultats dont nous avons besoin.select(*)
n'est utilisé qu'en tant que sous-sélection ? Puisqu'il s'agit d'une sélection intégrée, MySQL ne serait-il pas assez intelligent pour déterminer les colonnes réelles qui doivent être sélectionnées?