Nan, c'est pas ce que je voulais dire dans l'absolu, mais concernant les datetime cela peut être ambigu. C'est ce que j'expliquais dans ce message
Nan, c'est pas ce que je voulais dire dans l'absolu, mais concernant les datetime cela peut être ambigu. C'est ce que j'expliquais dans ce message
je t'avais bien lu
il n'empêche que ça peut être plus optimisé surtout sur des gros traitement car là tu es sur qu'il voit ça comme un opérateur ternaire alors que je suis pas sur que l'optimiseur cherche l'équivalence avec l'écriture que tu préconises... je pense qu'il voit ça comme 2 comparaisons séparées et un and en plus...
toujours pas résolu?
J'ai voulu vérifier pour en avoir le coeur net sur une table MyISAM de 524 670 lignes ou j'ai le champ "Date_compteur" de type datetime en clé primaire. Les deux autres champs sont de type smallint et int et sont non indexés.
Ces deux requêtes sont équivalentes en terme de performances (au dix millième de seconde près, le reste n'étant pas significatif).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 $query = "SELECT count(*) FROM compteur_visiteurs_test"; $query1 = "SELECT Date_compteur, Nombre_visiteurs, Total_visiteurs FROM compteur_visiteurs_test WHERE Date_compteur >= DATE_SUB('$date', INTERVAL 2 MONTH) AND Date_compteur <= LAST_DAY('$date')"; $query2 = "SELECT Date_compteur, Nombre_visiteurs, Total_visiteurs FROM compteur_visiteurs_test WHERE Date_compteur BETWEEN DATE_SUB('$date', INTERVAL 2 MONTH) AND LAST_DAY('$date')"; $ressource = mysqli_query(Con_li::getC(),$query); $time1 = microtime(true); $ressource1 = mysqli_query(Con_li::getC(),$query1); $time_end1 = microtime(true); $time2 = microtime(true); $ressource2 = mysqli_query(Con_li::getC(),$query2); $time_end2 = microtime(true); echo 'nombre lignes = '.mysqli_fetch_row($ressource)[0]; echo '<br>'; echo 'operateur = '.($time_end1 - $time1); echo '<br>'; echo 'between_ = '.($time_end2 - $time2); echo '<br>'; echo 'nb_resultats_1 = '.mysqli_num_rows($ressource1); echo '<br>'; echo 'nb_resultats_2 = '.mysqli_num_rows($ressource2);
Par contre si l'on élargi la recherche sur 20 ans (...INTERVAL 20 YEAR) AND... la requête avec les opérateurs de comparaison est quasiment systématiquement plus rapide de deux millièmes de secondes.nombre lignes = 524670
operateur = 0.00073599815368652
between_ = 0.00074887275695801
nb_resultats_1 = 91
nb_resultats_2 = 91
Toujours avec ce même interval de 20 ans les requêtes redeviennent équivalentes en performances si je ne récupère plus que le champ "Date_compteur" (SELECT Date_compteur FROM compteur_visiteurs_test...)nombre lignes = 524670
operateur = 0.02649188041687
between_ = 0.028257846832275
nb_resultats_1 = 7335
nb_resultats_2 = 7335
Mais de nouveau la requête avec les opérateurs de comparaison semble reprendre un léger avantage si le seul champ récupéré n'est pas le champ "Date_compteur" (SELECT Nombre_visiteurs FROM compteur_visiteurs_test...)
D'après mes tests je ne constate donc jamais aucune performance supplémentaire en utilisant between sur des champs datetime. Je ne dis pas que c'est toujours le cas mais sur cette table qui fait tout de même plus de 500 000 enregistrements je n'ai pas encore trouvé d'exemples concluants en sa faveur (et j'obtiens les mêmes résultats si je change mon datetime en date, ou encore si j'inverse l'ordre d'exécution des requêtes).
Cela confirme donc au moins en partie (sur les tables MyISAM) le conseil des anciens quand ils disent qu'au regard des pb que cela peut poser par ailleurs, l'utilisation de between sur les champs date ne s'impose pas naturellement.
intéressant ce qui prouve bien que l’optimiseur les traite différemment déjà...
comme je le pensais mais l'optimisation de l'arbre d'exécution est surprenante...
tu as bien désactivé les mécanismes d'optimisation des requêtes répétitives s'il est activé car pour ce genre du test ça fausse les valeur à cause des première exécution, de même que le buffer de données...?
tu as fais la moyenne sur combien d'essais? parce que php et les mesures de performances... quand je vois les écarts qu'on obtient en c/c++ pour tester une fonction...
d'ailleurs c'est un truc qui manque dans mysql, tu peux tester ce que tu mets dans la partie select mais tu as rien pour faire de la mesure de temps d'exécution sur une requête complète...
là en php tu as les aléas d'exécution du php, des communications tcp/ip et enfin ceux de l'exécution coté mysql...
enfin vu les écarts on peut dire que c'est pleinement identique avec respectivement 1 et 8% d'écart entre eux dans l'ordre de tes tests...
J'ai touché à rien, et je n'ai rien activé, les conditions sont identiques pour toutes les requêtes.
Et oui j'ai fait de nombreux essais, plusieurs dizaines pour chaque test. Les résultats sont pratiquement toujours les mêmes.
Je ne m'explique pas le fait que la requête avec les opérateurs de comparaison soit un peu plus rapide si je récupère tous les champs, ou si je ne récupère pas uniquement le champ date. Autant cela me semble logique que d'éventuels petits écarts puissent être constatés quand on augmente l'étendue des recherches autant je ne m'attendais pas à des écarts possibles concernant le nombre et la qualité des champs retournés (en passant d'une requête à l'autre)...
Enfin bon globalement dans mon test on peut dire qu'il n'y a pas de différence significative et qu'il n'y a pas lieu de privilégier l'une ou l'autre si l'on considère uniquement le plan des performances.
oui les bizarreries de leur programmation...
normalement soit A un ensemble de valeurs alors tu peux voir:
comme étant:(A<=b) et (A>=c)car le et fait ressortir l'intersection des sous-ensembles obtenus par chaque comparaison...((A<=b)>=c)
tu peux utiliser ça facilement directement dans un opérateur ternaire où tu sais à l'avance que tu es dans ce cas...
tu peux le faire aussi pour un ensemble d'opérations séparée par des "et" mais ça implique de le détecter en phase d'optimisation ce qui devrait être plus long donc...
bref... c'est ce que je te disais en réponse à ton test de toute façon c'est pareil d'utiliser l'un ou l'autre... (tu remarqueras comme j'ai toujours utilisé du conditionnel tellement mysql peut être surprenant parfois...)
Pour terminer et être plus complet je rajoute ma config de test :
APACHE 2.4.2
MYSQL 5.5.25a
PHP 5.4.4
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager