bonjour, je suis complètement débutant et me pose quelques questions relatives à la performance d'un site en local que je tente de développer.
J'ai une table unique de 86000 lignes, environ 250 colonnes, qui est une liste d'objets, indexés par un champ id
les autres colonnes représentent des caractéristiques de ces objets, par exemple name, classes, itemtype, slots, reqlevel, taille, couleur, grosseur, etc etc...
mon code php boucle sur un array appelé $slot qui contient 17 valeurs, puis sur un array $class qui en contient 15 donc 255 requêtes suivantes :
1 2 3 4 5
| foreach ($slot as $key=>$value) {
foreach ($level as $keyl=>$valuel) {
$sqltest='SELECT `id`,`name`,IF(`reclevel`<'.$keyl.','.$fieldsort_select.',ROUND('.$fieldsort_select.'*'.$keyl.' / `reclevel`)) AS displayed FROM `items` WHERE `itemtype` <> 54 AND `classes` & '.$class_select.' AND `slots` & '.$key.' AND `reqlevel`<='.$valuel.' AND `reclevel`<='.$keyl.' AND `races`<>0 AND `races`<>65536 AND `notransfer`=0 ORDER BY `displayed` DESC LIMIT 10';
}
} |
et en gros ca me prend 255*1/2s pour effectuer ces boucles ce que je trouve trop long.
les choses que j'ai remarqué après avoir lu les diverses FAQ et pages concernant l'optimisation sont les suivantes :
a) ORDER BY effectivement plombe les performances, si je l'enlève de la requête j'arrive effectivement à des bien meilleurs résultats, le problème devient alors : est-il plus rapide de classer mes résultats en PHP que ce que mysql va faire, j'espère ne pas m'emmêler les pinceaux mais si je supprime ce ORDER BY je vais devoir changer la structure de mon code en php.
b) j'ai testé en indexant le paramètre sur lequel ORDER BY est effectué, cela améliore sensiblement le temps de chaque requête c'est appréciable, le problème dans mon cas est double :
-d'abord je ne sais pas d'avance sur quel champ je vais effectuer cette requête et donc potentiellement si je devrais indexer tous les champs de ma table, n'ayant pas d'expérience en programmation et base de donnée ca me paraît extrême mais bon pourquoi pas. autre possibilité peut etre est d'indexé le champ quand la requête se lance, je ne sais pas si cela est très propre.
-et deuxièmement, ce ORDER BY peut être effectué sur une combinaison linéaire de différents champs ce qui a mon avis rend l'indexation de tous les champs inutile au moins dans ce cas. pour donner un petit exemple, une requête simple serait effectué avec un $fieldsort_select qui vaut 'mana':
SELECT `id` , `name` , IF( `reclevel` <5, `mana` , ROUND(`mana`*5 / `reclevel` ) ) AS displayed FROM `items` WHERE `itemtype` <>54 AND `classes` &2 AND `slots` &4 AND `reqlevel` <=5 AND `reclevel` <=5 AND `races` <>0 AND `races` <>65536 AND `notransfer` =0 ORDER BY `displayed` DESC LIMIT 10
et par exemple sur un $fieldsort_select qui est égal à 'mana*5+hp*10':
SELECT `id` , `name` , IF( `reclevel` <5, ('mana*5+hp*10) , ROUND(('mana*5+hp*10)*5 / `reclevel` ) ) AS displayed FROM `items` WHERE `itemtype` <>54 AND `classes` &2 AND `slots` &4 AND `reqlevel` <=5 AND `reclevel` <=5 AND `races` <>0 AND `races` <>65536 AND `notransfer` =0 ORDER BY `displayed` DESC LIMIT 10
c) le mot clé explain devant ma requête ne m'apporte pas grand chose, du moins je n'en tire pas grand chose à mon niveau.
voilà pour une requête particulière de la boucle :
1 2 3 4
|
EXPLAIN SELECT `id` , `name` , IF( `reclevel` <5, `mana` , ROUND(`mana`*5 / `reclevel` ) ) AS displayed FROM `items` WHERE `itemtype` <>54 AND `classes` &2 AND `slots` &4 AND `reqlevel` <=5 AND `reclevel` <=5 AND `races` <>0 AND `races` <>65536 AND `notransfer` =0 ORDER BY `displayed` DESC LIMIT 10
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE items ALL NULL NULL NULL NULL 86374 Using where; Using filesor |
d) analyze table ne me dit rien
voilà j'espère avoir décrit de manière clair mes interrogations et merci d'avance de votre lecture.
Partager