[MySQL] Question rapide sur efficacité d'une requête

Question rapide sur efficacité d'une requête [MySQL] - SQL/NoSQL - Programmation

Marsh Posté le 18-09-2006 à 09:18:04    

Salut,
 
Je me pose une question.
 
J'ai une table, contenant deux champs:  
-value, de type INT
-completed, de type SMALLINT, contenant 0 ou 1.
 
Je pose une Index sur mon champ value.
Je peux poser un index sur le champ completed s'il le faut. (efficacité?)
 
Le but de ma requête est de sélectionner tous les enregistrements dont value est inférieur à disons 10000. Je sais que dans ce cas, completed sera placé à 0.
 
Vaut il mieux que je fasse un:
 
WHERE value < 10000
 
Ou alors un:
 
WHERE compeleted = 0 AND VALUE < 10000
 
La question est en gros de avoir si ça vaut le coup de filtrer grâce à completed, sachant que les enregistrements retournés seront les mêmes.
 
Est ce que ça vaut le coup d'indexer completed? (je sais que normalement, on n'indexe pas les champs pouvan contenir peu de valeurs différentes, mais là, en l'occurence, cette valeur booléenne me permet de filtrer)
 
Pour info, je précise que j'utilise des tables de type MyISAM, et que les requêtes sous MySQL ne peuvent utiliser qu'un seul index à la fois.
 
Merci.
 
Edit: remplacement de ">" par "<" dans mon exemple (mais la question et les enjeux restent les mêmes)


Message édité par Yoyo@ le 18-09-2006 à 10:39:57
Reply

Marsh Posté le 18-09-2006 à 09:18:04   

Reply

Marsh Posté le 18-09-2006 à 10:33:49    

Pourquoi tu fais pas directement  
WHERE compeleted = 0
 
sans le > 10000 avec un index sur completed seulement
 
Rien de sert de mettre les deux filtres si les deux ramènent les mêmes résultats. J'utiliserai plutot Completed que value, regarde en testant ce que ça donne

Reply

Marsh Posté le 18-09-2006 à 10:39:15    

Non, les filtres ne ramènent pas systématiquement les mêmes valeurs, ce n'est pas exactement ce que j'ai dit:
 
J'ai dit que tous les enregistrements ayant une value < 10000 auraont un completed à 0, mais par contre, je n'ai pas dit que tous les enregistrements ayant un completed à 0 auraont une value < 10000...
 
C'est une petite nuance.
 
En gros, tester le completed égal à 0 ne rapportera pas moins d'enregistrements, mais par contre, je me demandais si ça ne pouvat pas aider à faire un préfiltrage.

Reply

Marsh Posté le 18-09-2006 à 10:42:38    

Si on prend en compte la nuance ;) , A mon avis ca ne sert à rien puisque de toute façon faudra qu'il refasse le test  value < 10000.
Ca va complexifier ta requête.
 
Mais le plus simple c'est de faire le test...

Reply

Marsh Posté le 18-09-2006 à 10:47:49    

Bah en fait,
 
Je me disais que s'il commençait par filtrer en utilisant le completed = 0, il aurait ensuite beaucoup moins d'enregistrements à tester (value<10000).
 
En ce qui concerne de tester, le problème, c'est qu'il me faudrait un jeu de données vraiment gros pour pouvoir obtenir des temps de réponse significatifs (car ces requêtes restent simples), chose que je n'ai pas.
Bien entendu, je pourrais créer un script qui m'insérerait des tonnes de données, mais je posais la question au cas il y aurait déja une réponse à ma question sans avoir à tester.
 
D'autre part...je n'ai jamai scompris, dans MySQL Query Browser, la signification des deux chiffrs correspondant aux temps d'exécution de la requête...

Reply

Marsh Posté le 18-09-2006 à 14:09:16    

avant de parler d'optimisation, parle de fonctionnel.
 
est-ce que sémantiquement, le test sur completed = 0 a un sens ?
il faut garder à l'esprit que ta requête c'est pas du oneshot, et qu'elle sera utile aussi pour des valeurs > 10000.
a ce moment, différencier les valeurs de completed est-il utile ?
 
je prend par exemple le cas de l'ERP sur lequel je travaille.
 
un évènement est identifié par la clé composite suivante :
codsoc = société
achvte = achat/vente
typeve = type d'évènement
numeve = numéro d'évènement
 
le paramétrage impose que les numeve soient différents pour chaque évènement, quels que soient leur type au sein d'une même société.
la clé pourrait donc être tout bêtement codsoc/numeve
 
mais
 
est-ce que ça à un sens de recherche un évènement par son numéro sans savoir ce que c'est ? non
 
alors le typeve doit absolument être intégré à la clé, même s'il n'apporte rien à l'index de clé primaire.
 
ensuite, une commande (typeve = CDE) ça peut être une commande d'achar (achvte = A) ou de vente (achvte = V). à nouveau, est-ce que ça à un sens de savoir si je recherche une commande donnée sans savoir si c'est une vente ou un achat ? non. à nouveau, achvte doit être ajouté à la clé, même si ça n'apporte rien à la clé.
 
pour finir, j'ai un code état (codeta). est-ce que ça à un sens de savoir si je cherche une commande de vente sans savoir si elle est validée ou soldée ? oui. à ce moment, le codeta ne sera pas membre de la clé.
 
bref, dans ton cas on ne parle que d'index et de critère, alors que moi je parle de clé. mais la problématique revient au même. la question est donc "est-ce que ça a un sens ?". je ne connais pas tes données, mais c'est comme faire des plans sur la comète dans mon cas, et se dire que tout évènement dont le dateve < 20051231 sera forcément soldé ou annulé, ce qui est vrai. cependant, jamais de la vie je vais ajouter ce type de clause, tout simplement parceque le jour où on réutilise cette requête pour une autre date, la requête devient fausse, et surtout, si par hasard j'ai des données "incohérentes" d'un point de vue logique, mais cohérentes d'un point de vue fonctionnel, je ne vais pas les retrouver. il est donc impératif de ne se baser que sur le fonctionnel pur, sans faire de suppositions logiques.
 
c'est avec ce genre de plans sur la comète que ce matin je me suis paluché des centaines de lignes de paramétrage d'un flux extrêment complexe afin de trouver un bug dans une procédure de calcul de stocks. tout simplement parceque j'ai supposé que si un produit était en stock et n'avais pas de réservation, il ne pouvait pas correspondra à une commande en relicat... ben si. (erreur de saisie, mais rien ne l'empêche d'un point de vue fonctionnelle : une commande passée en 2004 avec une livraison prévue en 4004... c'est ballo, mais du coup elle est en relicat et pourtant n'apparaît pas dans le suivit des évènements puisque la date est future)

Reply

Marsh Posté le 18-09-2006 à 14:30:06    

Merci pour ta réponse.
 
Bien évidemment, quand j'ai posé ma question, j'ai simplifié le problème à l'extrêm, pour le rendre rapidement abordable.
 
En gros, le champ value correspond à une date (de tpe UNIX timestamp, donc, un entier). Appelons le nextDate.
 
Pour ma part, je ne veux considérer que les enregistrements dont nextDate est inférieur au timeStamp courant.
 
Le champ completed est là dans le but d'ignorer les enregistrements ayant un completed = 1.
 
Il a un côté redondant, vu que pour ignorer un enregistrement, il me suffit, à partir du moment où je veux l'ignorer, de mettre son champ NextDate à une valeur qui ne sera jamais atteinte dans un laps de temps réaliste (par exemple, le mettre à une valeur qui correspond à une date en 2003). Cependant, sémantiquement, il veut mieux avoir un champ completed mis à 1, ça rend la bdd plus lisible... (mais je continuerai à mettre mon nextDate à une date non atteignable, même si je mets le completed à 1. De cette manière, ça rend mes données plus robustes, et je ne m'amuserai pas à supposer que toute personne manipulant mes données pensera à mettre le completed à 1.)
 
Donc, pour en revenir à mes moutons, tous mes enregistrement pourraient être filtrés avec le nextDate (je teste que nextDate est inférieur à la date du jour), mais j'ai la possibilité de me servir de mon "completed" en complément.
La question est de savoir si ça vaut le coup.
 
 

Reply

Marsh Posté le 18-09-2006 à 14:35:06    

/me n'a rien compris.
 
si j'ai bien compris, ton "completed" est calculé ?
 
donc selon la réponse à cette question :
-> Est-ce qu'il est extrêmment utile, genre sert-il de façon critique pour optimiser des requêtes lourdes ou non. (comme peut l'être un "total" sur une entête de commande).
 
dans ton cas, j'en doute, puisqu'il est à la fois redondant avec la date, et perd des informations.
 
bref : non seulement tu n'indexes pas le champ, mais surtout tu le vires de ta table ;)
 
c'est du moins mon avis selon le peut que j'ai compris de ton explication ;)

Reply

Marsh Posté le 18-09-2006 à 14:44:12    

MagicBuzz a écrit :

/me n'a rien compris.
 
si j'ai bien compris, ton "completed" est calculé ?
 
donc selon la réponse à cette question :
-> Est-ce qu'il est extrêmment utile, genre sert-il de façon critique pour optimiser des requêtes lourdes ou non. (comme peut l'être un "total" sur une entête de commande).
 
dans ton cas, j'en doute, puisqu'il est à la fois redondant avec la date, et perd des informations.
 
bref : non seulement tu n'indexes pas le champ, mais surtout tu le vires de ta table ;)
 
c'est du moins mon avis selon le peut que j'ai compris de ton explication ;)


 
Je ne sais pas ce que tu entends par "calculé" (calculé en temps réel ou alors mis à jour à 1 , une fois que nécessaire, par le système gérant ma bdd?
 
En tout cas, oui, ce champ a un côté redondant, puisqu'il ne sera à 1 que pour les champs ayant un nextDate correspondant à un futur très lointain.
 
Cependant, je tiens quand même à le garder dans ma bdd, car il permet de connaître très facilement les enregistrements actifs (cad avec un completed à 0), par exemple, pour connaître le ratio completed/total.
 
Et puis, je trouve ça très moche de devoir mettre un cahmp date à une date très lointaine pour pouvoir ignorer les enregistrements en question. Je le fais quand même, car ça permet de rester dans la logique "ignorer les enregistrements dont le NextDate est > à la date actuelle" (il faut bien que je donne une avleur à ce NextDate, même si je n'ai plus besoin de considérer l'enregistrement en question)
 
(est ce que tu penses avoir compris le contexte ou pas?)

Reply

Marsh Posté le 18-09-2006 à 15:17:15    

et null alors c'est pas fait pour les bisounours :o

Reply

Marsh Posté le 18-09-2006 à 15:17:15   

Reply

Marsh Posté le 18-09-2006 à 15:26:57    

Je préfère éviter les Nulls dans les champs où c'est facilement faisable.
 
Je vaus quand même reconsidérer ce fait et peut être autoriser les Nuls, mais j'ai pas confiance en l'utilisation que pourraient en faire d'autres personnes (car tu dois le savoir, mais souvent , les Nulls sont considérer comme des valeurs fourre tout, ce qui n'est pas hyper sain)
 
Mais bon, en supposant que je n'ai pas mes nulls, et si on tente de répondre à lma question initiale: est ce que ça vaut le coup de filtrer ma requête avec un Completed = 0 d'un point de vue de rapidité d'exécution (avec le temps, completed = 0 ne représentara qu'une infime partie des enregistrements, donc, ça peut permettre un bon travail de dégrossissement)
 
Il fau tbien se mettre dans le contexte MySQL où il 'y a pas de clustered index, donc, j'ai peur que les requêtes sur intervalle (myvalue<10000) s'avèrent lentes dans le cas de grosses tables.
Si je pouvais utiliser un clustured index, je ne me poserais même pas la question.

Reply

Marsh Posté le 18-09-2006 à 16:46:04    

point de vue rapidité, je ne suis pas sûr que tu voies grand chose. mais bon, si le completed à ce moment à effectivement un sens, pkoi pas.

Reply

Marsh Posté le 18-09-2006 à 16:47:43    

sinon, clustered ou non, l'index sera de toute façon trié, donc mise à part sauter directement un noeud dans l'arbre de tri, je ne vois pas l'intérêt de rajouter ce champ dans l'index (à mettre en premier évidement).
 
par contre, vas-y le déséquilibre de l'arbre à chaque fois que tu vas changer ce flag... c'est pas forcément recommandé

Reply

Marsh Posté le 18-09-2006 à 16:55:47    

On a dû mal se compredre:
 
Si je pouvais utiliser des Clustered Index dans ma table alors je n'utiliserais même pas mon Completed. Je mettrais un Clustered Index sur NextDate, et paf, mon range serait tretrouvé sans avoir à trier quoique ce soit, en utilisant uniquement le clustered index sur NextDate pour retrouver les bons champs.
 
Now, utiliser un Clustered Index est exclu (je suis sous MySQL)
 
En admettant que je mette un unique index sur NextDate, je me demande si la vitesse d'exécution sera optimale.
Peut être que finalement, en ne mettant mon index que sur Completed, et vu que ce champ va devenir de plus en plus sélectif avec le temps (de plus en plus d'enregistrements seront "Completed" ), je me dis que cette soluton pourrait être plus efficace.
 
En aucun cas, je n'envisageais d'index double. (ou plutôt je n'y avais pas pensé). En fait, le plus efficace serait un index double sur (Completed, NextDate) mais comme tu dis, lors de la MaJ de Completed, ça va mettre le chantier dans mon index. (mais remarque, le NextDate aussi est Mis à Jour si je n'utilise pas de Completed, et donc, là aussi, il va y avoir un chagement dans l'index portant sur Completed)

Reply

Marsh Posté le 18-09-2006 à 17:13:08    

comme j'ai dit, ça changera rien (ou presque) si tu rajoutes completed à ton index.
par contre, lors des maj de completed (qui doit être en première place de l'index pour être utile) tu vas fortement déséquilibrer ton arbre, ce qui est donc pas forécément intéressant.
 
car je maintiens, si les données ne sont pas triées sur le disque, les idenx sont des arbres logiques, donc triés, et qui doivent rester équilibrés pour avoir le max de performances

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed