Optimiser une requete MySQL

WRInaute accro
J'ai une table avec disons 10 000 insertions et pas mal de champs.


Je voudrais retirer les 10 dernières insertions avec quelques conditions sur les champs.


J'ai essayé deux technique, une boucle en php décroissante qui s'arrete quand j'arrive à i=10 mais on m'a dit "tu es en train de faire une usine à gaz apprend à faire des requete"


J'ai alors fait une vrai requete sql, select * etc... Avec limit 0, 10, se qui me renvoit bien sur le meme résultat.


Cependant avant de me renvoyer le résultat toutes les insertions sont listés, en gros mysql examine les 10 000 insertions, se qui est très lent sachant que la table grossit de jour en jour.


Comment faire donc pour récuperer, sans tout parcourir et de façon optimisée, les 10 dernières insertions.
 
WRInaute discret
JeunZ a dit:
Cependant avant de me renvoyer le résultat toutes les insertions sont listés, en gros mysql examine les 10 000 insertions, se qui est très lent sachant que la table grossit de jour en jour.
Non, si tu mets limit 0,10 la requête s'arrête dès qu'elle a ses 10 éléments.
Maintenant, pour accélérer les choses, l'idéal est d'avoir un index par champ que tu utilises dans ta sélection (si tu as une clause WHERE).
 
WRInaute accro
Ba je fais bien un limite 0,10 mais dans mes "slow query" je retrouve toujours la requete avec 10 000 insertions examinées.


Ce serait alors parsqu'il part de 0 à 10 000 pour trouver les 10 derniers, comment faire pour qu'il parte de la fin, car en effet si on demande les 10 derniers et qu'on part du début.

edit: je met bien un "desc" et je classe sur mon champs "id"
 
WRInaute discret
Hum... Tu me poses une colle.
Question: comment fais-tu pour voir tes Slow queries ?
Dans phpMyAdmin je vois que j'en ai 22, mais je ne sais pas comment faire pour les voir :?:
 
WRInaute accro
Euhhh je suis allé dans mon serveur dans le repertoire ou j'ai mes logs sql...


Depuis que j'ai transformé le primary en index je n'ai plus eu de nouvelle slow query donc je surveille ça à l'air d'avoir joué mais bon j'attend confirmation ;-)

merci en tout cas
 
WRInaute occasionnel
si tu as d'autres champs qui se répettent (par exemple, l'identifiant d'un utilisateur qui ajoute un post dans un forum), tu peux aussi les passer en index, et optimiser (OPTIMIZE) ta table de temps à autre.
Avec cette technique, le serveur SQL ne lira que les lignes qui correspondent bien à l'utilisateur concerné.
plus d'infos par mp si tu veux, ou prends mon msn, je mords pas
 
WRInaute discret
Les 2 gros problèmes dans ce genre de requête :
- c'est les conditions de la requête ; une solution : mettre des index
- c'est le tri. Je suppose que pour rechercher les 10 dernieres lignes tu fais un truc genre ORDER BY no DESC LIMIT 0,10 . Il faut savoir qu'avec le ORDER BY mysql va regarder et classer les 10 000 enregistrements (c'est long), puis ensuite retrourner les 10 premiers éléments. Il n'y a pas de solution simple pour contourner ça.
 
WRInaute impliqué
Tu veux pas nous faire un copier coller de ta requête ?
(en changeant les noms des tables si t'as peur de les dévoiler)
 
WRInaute occasionnel
Il y a des solutions. Après, ça dépend du genre de champ que tu manipules.
Typiquement, tu fais une petite table qui va garder trace des 10 derniers inserts: quand tu insères un nouveau record dans ta table principale, tu insères aussi ton fameux champ dans la petite table, avec un auto-increment.
Ensuite quand tu veux récupérer les 10 derniers records de ta table principale, tu croises simplement avec la petite table et ça t'évite le order by sur 10 000 records.
En clair: la petite table PETITE contient un auto-increment (AUTOID) et une copie de ton fameux champ (FAMFIELD). Donc à chaque insert sur ta table principale:
insert TABLEPRINC values(FAMFIELD, le_reste_des_champs)
insert PETITE values(FAMFIELD)
Récupères alors la valeur correspondante de l'auto-increment et tu fais:
delete from PETITE where AUTOID < (lastvalue-10)
pour virer les lignes trop anciennes.

Enfin, pour récupérer tes 10 derniers records:
select TABLEPRINC.* from TABLEPRINC, PETITE where PETITE.FAMFIELD = TABLEPRINC.FAMFIELD

Pas sûr d'être très clair, mais grosso modo, c'est l'idée.
 
WRInaute accro
Blini ))> Mon admin serveur qui a mis le nez dans mes requetes l'autre jour m'a dit la même chose "Mauvais système changer système" et il m'a dit de passer par une autre table ou je metterai que les 10 derniers...

Il est vrai que le temps de réponse sera nettement meilleur.


Depuis hier j'ai en tout cas plus aucune slow-query...
 
WRInaute occasionnel
Je suis très con, c'est effectivement encore plus simple de dupliquer complètement (= tous les champs) les 10 derniers records dans la petite table... Ça évitera la jointure
 
WRInaute accro
Et meme mieux au lieu de dupliquer tous les champs, je duplique que ceux qui me sont nécessaires ;-)

Je vais essayer de faire ça cette aprem merci à tous :)
 
Discussions similaires
Haut