2011-03-13 3 views
0

J'ai ces deux tables:optimisation de requêtes Mysql aide

CREATE TABLE `cpuinfo` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `usagetime` datetime DEFAULT NULL, 
    `cpuusage` int(11) NOT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `id_UNIQUE` (`id`), 
    KEY `idx_usagetime` (`usagetime`), 
    KEY `idx_usage` (`cpuusage`)); 

CREATE TABLE `jobinfo` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `starttime` datetime NOT NULL, 
    `endtime` datetime DEFAULT NULL, 
    `jobname` text NOT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `id_UNIQUE` (`id`), 
    KEY `idx-startime` (`starttime`), 
    KEY `idx-endtime` (`endtime`)); 

cette requête: Utilisation

explain SELECT j.id, j.starttime, j.endtime, j.jobname, c.cpuusage 
    FROM (SELECT j.id, j.starttime, j.endtime, j.jobname, MAX(c.usagetime) AS usagetime 
      FROM jobinfo AS j 
     LEFT JOIN cpuinfo AS c ON c.usagetime <= j.starttime 
     GROUP BY j.id) AS j 
    JOIN cpuinfo AS c ON j.usagetime = c.usagetime 
ORDER BY j.starttime 

Il faut environ 10 minutes pour courir.

pour expliquer la commande, je suis arrivé cette sortie

id,select_type,table,type,possible_keys,key,key_len,ref,rows,Extra 
--------------------------------------------------------------------------- 
1,PRIMARY,<derived2>,ALL,NULL,NULL,NULL,NULL,4557,"Using filesort" 
1,PRIMARY,c,ref,idx_usagetime,idx_usagetime,9,j.usagetime,1,"Using where" 
2,DERIVED,j,ALL,NULL,NULL,NULL,NULL,4557,"Using temporary; Using filesort" 
2,DERIVED,c,index,idx_usagetime,idx_usagetime,9,NULL,2880,"Using index" 

Pouvez-vous me donner quelques conseils pour optimiser cette requête SQL?

Voici mon post orginal:

Mysql join with time matching

Répondre

0

Essayez:

SELECT ji.starttime, 
     ji.endtime, 
     ji.jobname, 
     (SELECT ci.cpuusage 
      FROM CPUINFO ci 
     WHERE ci.usagetime <= ji.endtime 
     ORDER BY ci.usagetime DESC 
     LIMIT 1) AS cpuusage 
    FROM JOBINFO ji 

est ici la sortie EXPLIQUEZ sur mon 05/01/49:

id select_type   table type possible_keys key key_len ref rows Extra 
------------------------------------------------------------------------------------------------ 
'1', 'PRIMARY',   'ji', 'ALL', NULL,   NULL, NULL, NULL, '12', '' 
'2', 'DEPENDENT SUBQUERY', 'ci', 'ALL', 'idx_usagetime', NULL, NULL, NULL, '6', 'Using where; Using filesort' 
0

Vous joindrez sur moins de comparaison:

c.usagetime <= j.starttime 

Cela signifie que chaque enregistrement cpu qui a une usagetime moins que le temps du démarrage du travail sera joint à l'enregistrement du travail. Cette requête va devenir de plus en plus lente au fil du temps puisqu'elle joindra des informations d'il y a des mois si elle est présente. Vous êtes uniquement intéressé par la dernière entrée avant l'heure de début du travail.

Si vous êtes assuré qu'il existe un enregistrement cpuinfo dans un certain laps de temps de l'heure de début du travail, remplacez-la par une recherche de plage.

c.usagetime between j.starttime and date_sub(j.starttime, interval 5 minute) 

Cela devrait l'accélérer considérablement. Le plus petit vous pouvez faire l'intervalle le mieux.

0

Vous pouvez essayer cette petite astuce:

SELECT j.id, j.starttime, j.endtime, j.jobname, c.cpuusage 
FROM 
(
    SELECT j.id, j.starttime, j.endtime, j.jobname, MAX(c.usagetime) AS usagetime 
    FROM jobinfo AS j 
    LEFT JOIN cpuinfo AS c 
    ON c.usagetime <= j.starttime 
    WHERE c.usagetime > DATE_ADD(j.starttime, INTERVAL -1 DAY); 
    GROUP BY j.id 
) AS j 
JOIN cpuinfo AS c 
ON j.usagetime = c.usagetime 
ORDER BY j.starttime; 

Cela devrait provoquer le serveur à prendre juste une partie de la table o cpuinfo, ni la totalité ou la moitié. PS: essayez de considérer la valeur d'intervalle, peut-être 5 minutes dans votre cas suffirait.