|
Publicité ' | |||||||||||||||||||||||
|
|
#1 | ||||
|
Membre du Club
![]() Frédéric Inscription : juin 2011 Messages : 53 ![]() |
Bonjour à tous,
J'ai une table en InnoDB qui a 2 millions d'enregistrements. (C'est uniquement parce que j'ai fait tourner un programme de test toute la nuit) Etant donné que cette table est énorme, je me suis aperçu qu'une de mes requêtes est lente ( +60s): Code :
Code :
Il y a 2 millions d’enregistrements ayant "aColumn" avec la valeur 1 et 4000 ayant la valeur 2. Vu le temps, j'ai l'impression que mysql utilise d'abord la colonne where, puis sur tous les résultats prends le max. Alors qu'il serait plus performant de retourner le premier max ou la condition est vrai. Existe-il une autre façon d'écrire cette requête ? Merci. |
||||
|
|
00
|
|
|
#2 | |
|
Expert Confirmé
![]() Inscription : mai 2002 Messages : 1 655 ![]() |
Citation:
Donc oui il est forcé de faire un scannage de table puis de trouver le max de ceci. Et je pense qu'un index du type : (aColumn, IndexedColumn) ne changera pas grand chose à cause de la diversité des données. |
|
|
|
00
|
|
|
#3 |
|
Expert Confirmé
![]() ![]() Avcxjo MoKoRetraité Inscription : novembre 2005 Messages : 2 531 ![]() |
Saluton,
Vu le contexte, essaye comme cela Code :
SELECT MAX(IndexedColumn) FROM ( myBigTable) GROUP BY aColumn
__________________
Kie lumo eksistas ankaŭ ombro troviĝas. L.L. Zamenhof articles : Comment émuler un tableau croisé [quasi] dynamique et : Une énigme mathématique résolue avec MySQL recommande l'utilisation de PDO (PHP5 Data Objects) |
|
00
|
|
|
#4 | |
|
Membre du Club
![]() Frédéric Inscription : juin 2011 Messages : 53 ![]() |
Citation:
|
|
|
|
00
|
|
|
#5 | |||
|
Membre du Club
![]() Frédéric Inscription : juin 2011 Messages : 53 ![]() |
Citation:
Je pense que si il existe une requête qui permet de faire faire à Mysql quelque chose comme ça ce serait plus rapide (La requête n'est pas bonne, c'est juste pour donner une idée): Code :
|
|||
|
|
00
|
|
|
#6 | |||
|
Expert Confirmé
![]() Inscription : mai 2002 Messages : 1 655 ![]() |
Citation:
Dans votre 1er poste vous dites que 4000 lignes ont la valeur 2 et .....1996000 ont la valeur 1. Ici vous cherchez le max de la valeur qui a 1. Donc non votre boucle while est encore plus archaïque que ce qu le sgbd fait et il n'y a pas moyen de l'optimiser. testez avec un index comme je vous l'ai indiqué mais il y a de grande chance qu'il ne l'utilise pas. En fait vous cherchez la 1ere ligne qui dispose de la condition aColumn = 1 ? A quoi sert le MAX dans votre 2eme exemple ? |
|||
|
|
00
|
|
|
#7 | |||||||
![]() ![]() |
Teste si cette requête est plus rapide :
Code :
Code :
Citation:
Si cette supposition est juste et si tu n'as pas supprimé des données, ceci devrait être plus rapide : Code :
__________________
Philippe Leménager. Ingénieur d'étude à l'École Nationale de Formation Agronomique. Mon blog sur la conception des BDD, le langage SQL, le PHP avec Zend Framework... « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau) À la maison comme au bureau, j'utilise Mandriva Linux ou Mageïa ! Soutenons l'industrie logicielle française ! Linuxiens, comptez-vous ! |
|||||||
|
00
|
|
|
#8 | ||
|
Expert Confirmé
![]() Inscription : mai 2002 Messages : 1 655 ![]() |
Et ceci ?
Code :
En viendra le limit. |
||
|
|
10
|
|
|
#9 | ||||||
|
Membre du Club
![]() Frédéric Inscription : juin 2011 Messages : 53 ![]() |
Citation:
Citation:
J'ai compris pourquoi la première requete avait été rapide : - Je fais les tests des différentes requêtes avec workbench. Il avait ajouté limit 0,1000 au select, d'ou les 1.7s. Avec un limit 0,3000000 on retombe dans les +60s Non, ce n'est pas le cas. |
||||||
|
|
00
|
|
|
#10 | |||
|
Membre du Club
![]() Frédéric Inscription : juin 2011 Messages : 53 ![]() |
Citation:
Maintenant, je fais face à un dilemme. Dois-je généraliser cette requête partout ou je fais des SELECT MAX() avec une condition WHERE qui ne porte pas sur l'index recherché... En tout cas, merci à tous les deux pour votre aide. |
|||
|
|
00
|
|
|
#11 |
![]() ![]() |
Nous ne t'avons pas conseillé de mettre un index sur aColumn car elle ne peut prendre que deux valeurs et l'index ne serait probablement pas utilisé. Ceci dit, tu peux essayer.
Si par contre tu as une recherche sur une autre colonne comptant un grand nombre de valeurs, l'index sera utilisé et ce genre de requête devrait être beaucoup plus rapide. À tester au cas par cas. Il me semble quand même un peu long qu'une recherche d'un MAX sur 2 millions de lignes mette autant de temps, même sans index sur la colonne cherchée !
__________________
Philippe Leménager. Ingénieur d'étude à l'École Nationale de Formation Agronomique. Mon blog sur la conception des BDD, le langage SQL, le PHP avec Zend Framework... « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau) À la maison comme au bureau, j'utilise Mandriva Linux ou Mageïa ! Soutenons l'industrie logicielle française ! Linuxiens, comptez-vous ! |
|
00
|
|
|
#12 | |
|
Membre du Club
![]() Frédéric Inscription : juin 2011 Messages : 53 ![]() |
Citation:
Pour les performances : Je fais ces tests sur un PC portable et je prends bien soin d’arrêter mysql entre chaque tests afin qu'il n'y ai rien en cache. En fait, au lieu de "généraliser cette requête a tous les SELECT MAX() avec une condition WHERE qui ne porte pas sur l'index recherché" Ce serait plutôt "généraliser cette requête partout ou je fais des SELECT MAX(anIndexedColumn) avec une condition WHERE qui ne porte pas sur un index" |
|
|
|
00
|
|
|
#13 |
![]() ![]() |
Si cette colonne non indexée a un grand nombre de valeurs différentes, il faut envisager de l'indexer.
Attention toutefois à ce que la taille des index ne dépasse pas la taille de la table ; ça deviendrait contre-productif.
__________________
Philippe Leménager. Ingénieur d'étude à l'École Nationale de Formation Agronomique. Mon blog sur la conception des BDD, le langage SQL, le PHP avec Zend Framework... « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau) À la maison comme au bureau, j'utilise Mandriva Linux ou Mageïa ! Soutenons l'industrie logicielle française ! Linuxiens, comptez-vous ! |
|
00
|
|
|
#14 | ||||||||
|
Membre du Club
![]() Frédéric Inscription : juin 2011 Messages : 53 ![]() |
Voici les explains des différentes requêtes que j'ai testé. (Désolé pour le formatage)
Code :
1, SIMPLE, NULL, NULL, NULL, NULL, NULL, NULL,NULL,"Select tables optimized away" Code :
1, SIMPLE, myBigTable,index,NULL,indexedColumn_IDX,4,NULL,1,"Using where" Code :
1,SIMPLE,myBigTable,ALL,NULL,NULL,NULL,NULL,212130,"Using where" J'ai l'impression que Mysql n'utilise pas le fait que indexedColumn soit un index. D'ailleurs si on fait un explain sur cette requête : Code :
id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra 1,SIMPLE,myBigTable,ALL,NULL,NULL,NULL,NULL,212130,"Using where" Entre temps, j'ai supprimé cette grosse table. Je fais tourner mon programme de test pour récréer une table de plusieurs millions d'enregistrements et pouvoir vérifier tout ça. Edit : J'obtiens bien les mêmes temps de réponses pour SELECT MAX(indexedColumn) WHERE... et SELECT MAX(nonIndexedColumn) WHERE... |
||||||||
|
|
00
|
Copyright © 2000-2012 - www.developpez.com