簡體   English   中英

MySQL查詢優化幫助

[英]Mysql Query optimization help

我有這兩個表:

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`));

使用此查詢:

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

運行大約需要10分鍾。

對於解釋命令,我得到了這個輸出

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"

您能給我一些技巧來優化此SQL查詢嗎?

這是我的原始帖子:

MySQL加入時間匹配

您正在加入小於比較:

c.usagetime <= j.starttime

這意味着使用時間少於作業開始時間的每個cpu記錄都將被加入到作業記錄中。 隨着時間的流逝,此查詢將變得越來越慢,因為它將加入幾個月前的信息(如果存在的話)。 您只對作業開始之前的最新條目感興趣。

如果確定在作業開始時間的一定時間內存在cpuinfo記錄,則將其更改為范圍搜索。

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

那應該大大加快速度。 越小,間隔越好。

您可以嘗試以下小技巧:

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;

這將導致服務器僅使用cpuinfo表的一部分,而不是整個表的一半。

PS:嘗試考慮間隔值,在您的情況下,也許5分鍾就足夠了。

嘗試:

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

這是我的5.1.49上的EXPLAIN輸出:

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'

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM