Optimisation de requêtes

Résolu
zeldoi5
Messages postés
58
Date d'inscription
mercredi 13 octobre 2004
Statut
Membre
Dernière intervention
13 novembre 2005
- 28 avril 2005 à 17:50
cs_Anthomicro
Messages postés
9433
Date d'inscription
mardi 9 octobre 2001
Statut
Membre
Dernière intervention
13 avril 2007
- 29 avril 2005 à 17:43
Bonjour tout le monde!
Dans le cadre d'un projet je dois réaliser des statistiques sous forme de graphiques et radars.
Pour ceci j'utilise JpGraph (j'ai aussi essayé ChartDirector)
Mais j'ai un gros soucis, car la requête que 'jeffectue à l'air de faire flancher le serveur (Xeon 700) sur lequel je travaille.

Je dois faire des moyennes sur des mesures inscrites en base tous les 1/4 heure :

<?
$dateToday = date("Y-m-d");
$annee = date("Y");
$mois = date("m");
$jour = date("d");
$heure = date("H");
$minute = date("i");
$seconde = date("d");
$s = 0;
$heureTotale = date("H:i:s");

//Etablit la connexion avec le serveur de base de données, ainsi qu'à la base
server_connect("localhost","","");
//Etablit la connexion à la base de données
bdd_connect("theBDD");

for ($h=12;$h <= $heure;$h++)
{
for ($m=0;$m <= 45;$m=$m+15)
{
$h1 = $h + 1;
$m0 = ":0";
$s0 = ":0";
$m1 = $m + 15;
$heureprecedente = $h .":". $m . $s0;
$heuresuivante = $h .":". $m1 . $s0;
if ($m < 45)
{
$query = 'select AVG(ms.MESURE_RAM), AVG(ms.MESURE_CPU), AVG(mme.TR), AVG(l.TR)'
. ' FROM mesure_syst ms, mesure m, mesure_meta mme, mesure_lan l'
. ' WHERE m.ID_MESURE = ms.ID_MESURE'
. ' AND m.ID_MESURE = mme.ID_MESURE'
. ' AND m.ID_MESURE = l.ID_MESURE '
. ' AND m.DATE_MESURE = "' . $dateToday . '" '
. ' AND m.HEURE_MESURE between "' . $heureprecedente . '" and "' . $heuresuivante . '" ';
}
else
{
$heureprecedente = $h .":". $m . $s0;
$m1 = 59;
$heuresuivante = $h .":". $m1 . $s0;
$query = 'select AVG(ms.MESURE_RAM), AVG(ms.MESURE_CPU), AVG(mme.TR), AVG(l.TR)'
. ' FROM mesure_syst ms, mesure m, mesure_meta mme, mesure_lan l'
. ' WHERE m.ID_MESURE = ms.ID_MESURE'
. ' AND m.ID_MESURE = mme.ID_MESURE'
. ' AND m.ID_MESURE = l.ID_MESURE '
. ' AND m.DATE_MESURE = "' . $dateToday . '" '
. ' AND m.HEURE_MESURE between "' . $heureprecedente . '" and "' . $heuresuivante . '" ';
}
$resultQuery = mysql_query($query);
$rowQuery = mysql_fetch_row($resultQuery);
$row1[$h] = $rowQuery[0]/1000;
$row2[$h] = $rowQuery[1];
$row3[$h] = $rowQuery[2];
$row4[$h] = $rowQuery[3];

$tx_RAM[$h] = $row1[0];
$tx_CPU[$h] = $row2[0];
$tx_META[$h] = $row3[$h];
$tx_LAN[$h] = $row4[$h];

echo("Charge RAM en performance entre $heureprecedente et $heuresuivante : $tx_RAM[$h] ");
echo("Charge CPU moyenne en performance entre $heureprecedente et $heuresuivante : $tx_CPU[$h]");
echo("Temps de réponse moyen en performance M entre $heureprecedente et $heuresuivante : $row3[$h]");
echo("Temps de réponse moyen LAN en performance entre $heureprecedente et $heuresuivante : $row4[$h]");

}
}

// ensuite vient l'affichage....... (je ne vais pas décrire la suite....)
?>

Apparemment le serveur flanche, car quand l'heure (c'est à dire la variable $heure) est inférieure à 12, ça fonctionne, mais après :
Fatal error: Maximum execution time of 30 seconds exceeded in d:\www\reporting\ben\ebl\courbes_4s.php on line 79

Avec la ligne 79 : $resultQuery = mysql_query($query);

Pouvez vous m'aider s'il vous plaît?
Ya t'il un moyens d'optimiser la requête? Ou même (solution pir) de fixer le temps d'excution de la requête à un temps supérieur que 30 secondes ??

24 réponses

cs_Anthomicro
Messages postés
9433
Date d'inscription
mardi 9 octobre 2001
Statut
Membre
Dernière intervention
13 avril 2007
9
29 avril 2005 à 12:43
Rajoute un index dans tes trois tables sur le champ "ID_MESURE"



Ensuite rajoute un index DANS la table mesure sur le champ DATE_MESURE et sur le champ HEURE_MESURE



ta requête devrait s'en trouver accélérée énormément vu le nombre d'enregistrements que t'as dans ta table.



Une fois les index rajoutés, exécute ta requête en rajoutant un EXPLAIN
devant (dans phpmyadmin) et copie le tableau que tu obtiens ici, pour
qu'on voit si l'optimisation a porté ses fruits.



a +




<hr size="2" width="100%">




<li>Entraide, dépannage et vulgarisation informatique: Mon site de vulgarisation informatique</li>
3
cs_Anthomicro
Messages postés
9433
Date d'inscription
mardi 9 octobre 2001
Statut
Membre
Dernière intervention
13 avril 2007
9
29 avril 2005 à 14:40
Quel est le message d'erreur précis :



$resultQuery = mysql_query($query) or die(mysql_error());

<hr size="2" width="100%">




<li>Entraide, dépannage et vulgarisation informatique: Mon site de vulgarisation informatique</li>
3
cs_Anthomicro
Messages postés
9433
Date d'inscription
mardi 9 octobre 2001
Statut
Membre
Dernière intervention
13 avril 2007
9
29 avril 2005 à 15:11
$query='SELECT AVG(ms.MESURE_RAM),
AVG(ms.MESURE_CPU), AVG(me.TR), AVG(l.TR) FROM mesure_syst
ms,mesure_meta mme, mesure_lan l INNER JOIN mesure m ON
m.ID_MESURE ms.ID_MESURE INNER JOIN mesure_meta mme ON m.ID_MESURE
mme.ID_MESURE INNER JOIN mesure_lan l ON m.ID_MESURE = l.ID_MESURE
WHERE m.DATE_MESURE = "' . $dateToday . '" AND m.HEURE_MESURE
between "' . $heureprecedente . '" and "' . $heuresuivante . '"';



^^


<hr size="2" width="100%">




<li>Entraide, dépannage et vulgarisation informatique: Mon site de vulgarisation informatique</li>
3
cs_Anthomicro
Messages postés
9433
Date d'inscription
mardi 9 octobre 2001
Statut
Membre
Dernière intervention
13 avril 2007
9
28 avril 2005 à 19:23
Salut,





tu peux nous coller les structures des tables suivantes : mesure_syst ms, mesure m, mesure_meta mme, mesure_lan l



stp ?



merci
<hr size="2" width="100%">




<li>Entraide, dépannage et vulgarisation informatique: Mon site de vulgarisation informatique</li>
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
zeldoi5
Messages postés
58
Date d'inscription
mercredi 13 octobre 2004
Statut
Membre
Dernière intervention
13 novembre 2005
2
29 avril 2005 à 09:33
Merci de ton intérêt (désolé du retard pour répondre, mais j'ai perdu ma synchro hier...)
Alors je reprends
Tu veux les structures de mes tables, les voici :

Pour la table mesure_syst : Pour la table mesure : Pour la table mesure_lan :

int(11) ID_MESUREID_MESURE_LAN
ID_MESURE int(11) ID_MESURE int(11) ID_MESURE int(11)
MESURE_CPU double HEURE_MESURE time <LABEL for= checkbox_row_4> TR </LABEL> float
<LABEL for =checkbox_row_4>MESURE_RAM double DATE_MESURE date
RAM_SIZE double

Pour la table mesure_meta :

ID_MESURE_META int(10)
ID_MESURE int(11)
TR float

Je fais mes jointures sur les champs en italique, et je relève les champs en gras.
Voilà.
Sinon j'ai augmenté le temps d'excution du script php (par max_execution_time(60) dans php.ini)
ou j'aurai pu mettre dans le script set_limit_time(30) ...) ca permet d'executer les requêtes.... Mais ça n'est pas optimiser....
</LABEL>
0
cs_Anthomicro
Messages postés
9433
Date d'inscription
mardi 9 octobre 2001
Statut
Membre
Dernière intervention
13 avril 2007
9
29 avril 2005 à 10:51
Non je voudrais la structure du genre ça :



CREATE TABLE `connectes` (
`ip` int(9) unsigned NOT NULL default '0',
`pseudo` varchar(20) NOT NULL default '',
`temps` int(10) unsigned NOT NULL default '0',
`page_titre` varchar(100) NOT NULL default '',
`page_url` varchar(200) NOT NULL default '',
UNIQUE KEY `ip` (`ip`)
) TYPE=HEAP;



<hr size="2" width="100%">




<li>Entraide, dépannage et vulgarisation informatique: Mon site de vulgarisation informatique</li>
0
zeldoi5
Messages postés
58
Date d'inscription
mercredi 13 octobre 2004
Statut
Membre
Dernière intervention
13 novembre 2005
2
29 avril 2005 à 11:42
Ben je ne peux pas trop te dire, car les tables sont déja crées en dur dans la base...
Néanmoins, je te fais un copié collé :
table Mesure :

Champ |
Type |
Attributs |
Null |
Défaut |
Extra |
Action |
----

,
<LABEL for=checkbox_row_1>ID_MESURE</LABEL>,
int(11),
,
Non,
0

,
<LABEL for=checkbox_row_3>DATE_MESURE</LABEL>,
date,
,
Non,
0000-00-00

,
<LABEL for=checkbox_row_5>HEURE_MESURE</LABEL>,
time,
,
Non,
00:00:00

Table Mesure_lan :

<LABEL for=checkbox_row_1>ID_MESURE_LAN</LABEL>,
int(10) ,
UNSIGNED,
Non,
,
auto_increment

<LABEL for=checkbox_row_2>ID_MESURE</LABEL>,
int(10) ,
UNSIGNED,
Non,
0

<LABEL for=checkbox_row_4>TR</LABEL>,
float,
,
Non,
0

Table Mesure_syst :

<LABEL for=checkbox_row_1>ID_MESURE_SYST</LABEL>,
int(11),
,
Non,
,
auto_increment

<LABEL for=checkbox_row_2>ID_MESURE</LABEL>,
int(11),
,
Non,
0

<LABEL for=checkbox_row_3>MESURE_CPU</LABEL>,
double,
,
Non,
0

<LABEL for=checkbox_row_4>MESURE_RAM</LABEL>,
double,
,
Non,
0

Table Mesure_meta :

<LABEL for=checkbox_row_1>ID_MESURE_META</LABEL>,
int(10) ,
UNSIGNED,
Non,
,
auto_increment

<LABEL for=checkbox_row_2>ID_MESURE</LABEL>,
int(10) ,
UNSIGNED,
Non,
0

<LABEL for=checkbox_row_5>TR</LABEL>,
float,
,
Non,
0

C'est tout ce que je peux avoir....
0
cs_Anthomicro
Messages postés
9433
Date d'inscription
mardi 9 octobre 2001
Statut
Membre
Dernière intervention
13 avril 2007
9
29 avril 2005 à 12:12
Dans phpmyadmin tu peux avoir accès à la structure de la table, tu
cliques sur "exporter" tu coches "structure" et tu décoche
"transmettre".

<hr size="2" width="100%">




<li>Entraide, dépannage et vulgarisation informatique: Mon site de vulgarisation informatique</li>
0
zeldoi5
Messages postés
58
Date d'inscription
mercredi 13 octobre 2004
Statut
Membre
Dernière intervention
13 novembre 2005
2
29 avril 2005 à 12:23
Ok!
Désolé je ne savais pas :(

CREATE TABLE `mesure` (
`ID_MESURE` int(11) NOT NULL default '0',
`ID_SONDE` int(11) NOT NULL default '0',
`DATE_MESURE` date NOT NULL default '0000-00-00',
`HEURE_MESURE` time NOT NULL default '00:00:00',
PRIMARY KEY (`ID_MESURE`),
KEY `DATE_MESURE` (`DATE_MESURE`)
) TYPE=MyISAM;

CREATE TABLE `mesure_lan` (
`ID_MESURE_LAN` int(10) unsigned NOT NULL auto_increment,
`ID_MESURE` int(10) unsigned NOT NULL default '0',
`TR` float NOT NULL default '0',
PRIMARY KEY (`ID_MESURE_LAN`)
) TYPE=MyISAM AUTO_INCREMENT=39858 ;

CREATE TABLE `mesure_meta` (
`ID_MESURE_META` int(10) unsigned NOT NULL auto_increment,
`ID_MESURE` int(10) unsigned NOT NULL default '0',
`TR` float NOT NULL default '0',
PRIMARY KEY (`ID_MESURE_META`)
) TYPE=MyISAM AUTO_INCREMENT=39860 ;

CREATE TABLE `mesure_syst` (
`ID_MESURE_SYST` int(11) NOT NULL auto_increment,
`ID_MESURE` int(11) NOT NULL default '0',
`MESURE_CPU` double NOT NULL default '0',
`MESURE_RAM` double NOT NULL default '0',
`RAM_SIZE` double NOT NULL default '0',
PRIMARY KEY (`ID_MESURE_SYST`)
) TYPE=MyISAM AUTO_INCREMENT=53720 ;
0
malalam
Messages postés
10839
Date d'inscription
lundi 24 février 2003
Statut
Modérateur
Dernière intervention
2 mars 2010
25
29 avril 2005 à 12:28
Hello,



deja tu devrais reduire tes INT(11) et INT(10).

Enfin...sauf si tu comptes utiliser des nombres de 11 chiffres...ce qui m'etonnerait vu que php n'aimerait pas ca.
0
zeldoi5
Messages postés
58
Date d'inscription
mercredi 13 octobre 2004
Statut
Membre
Dernière intervention
13 novembre 2005
2
29 avril 2005 à 14:15
Ah ben je te le dis, l'execution est SUPER TOP améliorée!
Par contre j'ai besoin de votre aide, j'ai une requête qui merdouille :

La reqête qui me test entre x:45 et x:59 (avec x une heure) ne fonctionne pas, la voici :


$query = 'select AVG(ms.MESURE_RAM), AVG(ms.MESURE_CPU), AVG(mme.TR), AVG(l.TR)'
. ' FROM mesure_syst ms, mesure m, mesure_meta mme, mesure_lan l'
. ' INNER JOIN m.ID_MESURE = ms.ID_MESURE'
. ' INNER JOIN m.ID_MESURE = mme.ID_MESURE'
. ' INNER JOIN m.ID_MESURE = l.ID_MESURE '
. ' WHERE m.DATE_MESURE = "' . $dateToday . '" '
. ' AND m.HEURE_MESURE between "' . $heureprecedente . '" and "' . $heuresuivante . '" ';

Surtout que je l'ai essayé sur PhpMyAdmin (en changeant les inner join, sinon ça marche pas ) et ça fonctionne... Alors je ne sais plus quoi penser....
La voici en "format" phpMyAdmin.....


SELECT AVG( MESURE_RAM ) , AVG( MESURE_CPU ) , AVG( mesure_lan.TR ) , AVG(mesure_meta.TR )
FROM `mesure_syst` , `mesure` , `mesure_meta` , `mesure_lan`
WHERE mesure.ID_MESURE = mesure_syst.ID_MESURE
AND mesure.ID_MESURE = mesure_meta.ID_MESURE
AND mesure.ID_MESURE = mesure_lan.ID_MESURE
AND mesure.DATE_MESURE = "2005-04-29"
AND mesure.HEURE_MESURE
BETWEEN "06:45:00" AND "06:59:00"

Vous avez pas une idée?
0
cs_Anthomicro
Messages postés
9433
Date d'inscription
mardi 9 octobre 2001
Statut
Membre
Dernière intervention
13 avril 2007
9
29 avril 2005 à 14:17
Si elle fonctionne sous phpmyadmin c'est qu'il faut vérifier en php le
contenu des variables que tu mets dans la requête, si tu as bien mis
des quotes partout pour entourer les dates, etc...



Poste le EXPLAIN requête stp, qu'on voit si y'a moyen d'optimiser encore.



a +

<hr size="2" width="100%">




<li>Entraide, dépannage et vulgarisation informatique: Mon site de vulgarisation informatique</li>
0
zeldoi5
Messages postés
58
Date d'inscription
mercredi 13 octobre 2004
Statut
Membre
Dernière intervention
13 novembre 2005
2
29 avril 2005 à 14:22
D'abord, merci de te pencher sur mes problèmes.

Ensuite voici l'execution du explain request :

EXPLAIN SELECT AVG( MESURE_RAM ) , AVG( MESURE_CPU ) , AVG( mesure_lan.TR ) , AVG( mesure_meta.TR )
FROM `mesure_syst` , `mesure` , `mesure_meta` , `mesure_lan` WHERE mesure.ID_MESURE mesure_syst.ID_MESURE AND mesure.ID_MESURE mesure_meta.ID_MESURE AND mesure.ID_MESURE = mesure_lan.ID_MESURE AND mesure.DATE_MESURE = "2005-04-29" AND mesure.HEURE_MESURE
BETWEEN "06:45:00" AND "06:59:00"


Résultat :


table |
type |
possible_keys |
key |
key_len |
ref |
rows |
Extra |<!-- Results table body -->
----

mesure,
ref,
PRIMARY,DATE_MESURE,ID_MESURE,
DATE_MESURE,
3,
const,
68,
Using where,
----

mesure_syst,
ref,
ID_MESURE,ID_MESURE_2,
ID_MESURE,
4,
mesure.ID_MESURE,
1,
,
----

mesure_meta,
ref,
ID_MESURE,ID_MESURE_2,
ID_MESURE,
4,
mesure.ID_MESURE,
1,
Using where,
----

mesure_lan,
ref,
ID_MESURE,ID_MESURE_2,
ID_MESURE,
4,
mesure.ID_MESURE,
1,
Using where
0
cs_Anthomicro
Messages postés
9433
Date d'inscription
mardi 9 octobre 2001
Statut
Membre
Dernière intervention
13 avril 2007
9
29 avril 2005 à 14:25
Ok c'est parfait ;-)



rien à changer

<hr size="2" width="100%">




<li>Entraide, dépannage et vulgarisation informatique: Mon site de vulgarisation informatique</li>
0
zeldoi5
Messages postés
58
Date d'inscription
mercredi 13 octobre 2004
Statut
Membre
Dernière intervention
13 novembre 2005
2
29 avril 2005 à 14:34
J'ai fait un :
$resultQuery = mysql_query($query) or die("il y a une erreur ici !");

Pour voir si il n'y avait pas d'erreur...
Et il y en a une!!!
Voici l'affichage :

Requête effectuee : select AVG(MESURE_RAM), AVG(MESURE_CPU), AVG(TR), AVG(TR) FROM mesure_syst ms INNER JOIN mesure m ON m.ID_MESURE ms.ID_MESURE INNER JOIN mesure_meta mme ON m.ID_MESURE mme.ID_MESURE INNER JOIN mesure_lan l ON m.ID_MESURE = l.ID_MESURE WHERE m.DATE_MESURE = "2005-04-29" AND m.HEURE_MESURE between "00:45:00" and "00:59:00" il y a une erreur ici !

J'y comprends rien!
C'est la même que précédemment avec les champs de l'heure qui changent....
0
zeldoi5
Messages postés
58
Date d'inscription
mercredi 13 octobre 2004
Statut
Membre
Dernière intervention
13 novembre 2005
2
29 avril 2005 à 14:47
avec la requête suivante :


Code:
,
----

$query = 'select AVG(MESURE_RAM), AVG(MESURE_CPU), AVG(me.TR), AVG(l.TR)'
. ' FROM mesure_syst ms, mesure m, mesure_meta mme, mesure_lan l'
. ' INNER JOIN mesure m ' .
' ON m.ID_MESURE = ms.ID_MESURE'
. ' INNER JOIN mesure_meta mme' .
' ON m.ID_MESURE = mme.ID_MESURE'
. ' INNER JOIN mesure_lan l' .
' ON m.ID_MESURE = l.ID_MESURE '
. ' WHERE m.DATE_MESURE = "' . $dateToday . '" '
. ' AND m.HEURE_MESURE between "' . $heureprecedente . '" and "' . $heuresuivante . '" ';

Il m'accepte pas mes alias :

Not unique table/alias: 'm'
0
cs_Anthomicro
Messages postés
9433
Date d'inscription
mardi 9 octobre 2001
Statut
Membre
Dernière intervention
13 avril 2007
9
29 avril 2005 à 15:08
SELECT AVG(ms.MESURE_RAM),
AVG(ms.MESURE_CPU), AVG(me.TR), AVG(l.TR) FROM mesure_syst
ms,mesure_meta mme, mesure_lan l INNER JOIN mesure m ON
m.ID_MESURE ms.ID_MESURE INNER JOIN mesure_meta mme ON m.ID_MESURE
mme.ID_MESURE INNER JOIN mesure_lan l ON m.ID_MESURE = l.ID_MESURE
WHERE m.DATE_MESURE = "' . $dateToday . '" AND m.HEURE_MESURE
between "' . $heureprecedente . '" and "' . $heuresuivante . '"';




là ça fonctionne ?
<hr size="2" width="100%">




<li>Entraide, dépannage et vulgarisation informatique: Mon site de vulgarisation informatique</li>
0
zeldoi5
Messages postés
58
Date d'inscription
mercredi 13 octobre 2004
Statut
Membre
Dernière intervention
13 novembre 2005
2
29 avril 2005 à 15:16
Ben je vauis essayer, mais comme le serveur mettait 3plombes à répondre.... (apparemment 200 Server...) et bien j'ai décidé de le rebooter!
Donc une fois rebooté, je test!
Désolé pour l'attente!
0
zeldoi5
Messages postés
58
Date d'inscription
mercredi 13 octobre 2004
Statut
Membre
Dernière intervention
13 novembre 2005
2
29 avril 2005 à 16:46
Après plein de reboot à cause d'une requête SQL qui tournait en boucle...
J'ai décidé de virer les INNER JOIN
et cette requête semble fonctionner :

$query = 'select AVG(S.MESURE_RAM) , AVG(S.MESURE_CPU),AVG(E.TR),AVG(L.TR) '
. ' FROM mesure_syst S,mesure M,mesure_meta E,mesure_lan L'
. ' WHERE M.ID_MESURE = S.ID_MESURE'
. ' AND M.ID_MESURE = E.ID_MESURE'
. ' AND M.ID_MESURE = L.ID_MESURE'
. ' AND M.DATE_MESURE = "' . $dateToday . '" '
. ' AND M.HEURE_MESURE between "' . $heureprecedente . '" and "' . $heuresuivante . '" ';

Autre soucis qui s'est révelé, c'est un problème d'alias, j'ai donc choisi de ne mettre qu'une lettre en alias....
0
cs_Anthomicro
Messages postés
9433
Date d'inscription
mardi 9 octobre 2001
Statut
Membre
Dernière intervention
13 avril 2007
9
29 avril 2005 à 16:53
Ok du moment que t'as laissé les indexes c'est bon ;-)

<hr size="2" width="100%">




<li>Entraide, dépannage et vulgarisation informatique: Mon site de vulgarisation informatique</li>
0