J'ai une tâche CRON
qui doit extraire les clients avec des anniversaires dans un mois donné, à partir d'une table MySQL InnoDB. Le champ anniversaire est indexé et de type DATE
.
Filtrage pour avril, je peux interroger la table des clients soit par:
SELECT *
FROM customers
WHERE birthday LIKE "2015/04/%";
ou:
SELECT *
FROM customers
WHERE MONTH(birthday) = 4;
Lequel recommanderiez-vous et pourquoi?
L'intérêt d'utiliser DATE
comme type est pour que la base de données puisse interroger efficacement les données. C'est la même raison pour laquelle vous stockez un nombre sous la forme d'un INT
et non d'un VARCHAR
- afin que le moteur puisse prendre des décisions intelligentes. Si vous utilisez l'opérateur LIKE
à une date, vous perdez les avantages d'avoir choisi type de données correct .
L'utilisation de MONTH(birthday)
permet à MySQL de récupérer la partie mois de la colonne d'anniversaire dont il sait qu'elle respecte le format de données DATE
. Lorsque vous utilisez LIKE
, il fait une correspondance de modèle caractère par caractère, ce qui est beaucoup plus coûteux et plus lent à faire.
Si LIKE
était suffisant, alors MONTH()
n'existerait pas. Toute fonction intégrée va toujours être le choix sur LIKE
pour une requête DATE
.
J'irais pour:
SELECT *
FROM customers
WHERE MONTH(birthday) = 4;
... car c'est la façon la plus courante de sélectionner par mois. L'utilisation de MONTH()
appellera une fonction intégrée dans MySQL, mais si vous utilisez LIKE
, elle le prendra comme caractère puis effectuera la comparaison, donc au lieu de faire une opération, MySQL en exécutera deux.
(Plus d'un tas de commentaires, plus une réponse redondante.)
WHERE birthday BETWEEN '2015-04-01' AND '2015-04-01' + INTERVAL 1 MONTH
Pourrait utiliser INDEX(birthday)
, mais cela ne couvre que ceux qui vont naître le mois prochain.mnth TINYINT UNSIGNED COMMENT 'derived from MONTH(birthday)
, INDEX(mnth)
n'est peut-être pas utilisée. En effet, un pourcentage "important" de la table est souhaité. L'optimiseur peut décider qu'une analyse de table est aussi rapide.WHERE MONTH(birthday) = 4
est probablement la "meilleure" réponse.J'ai testé pour 100.000 rangs
SELECT * FROM customers WHERE MONTH(birthday) = 4
; ==> 18 secondes
SELECT * FROM customers WHERE birthday LIKE "2015/04/%"
; ==> 21 secondes