优化mysql查询(使用或创建索引)

时间:2012-11-15 10:22:17

标签: mysql select indexing

我有一个使PHP超时的SQL请求(mySQL 5.1.51)。 我想优化它,但我找不到缺少的东西。 请求是:

SELECT s_i.incident,
       s.hostname,
       a.application,
       s_ie.problem_status,
       s_i.open_time,
       s_i.close_time,
       s_ie.open_group,
       s_ie.primary_assignment,
       s_ie.closed_by_group,
       s_ie.contact_first_name,
       s_ie.contact_last_name,
       s_ie.description,
       s_ie.resolution,
       s_ie.famille_1,
       s_ie.famille_2,
       s_ie.famille_3,
       YEARWEEK(s_i.open_time)              AS 'semaine_ouverture',
       DATE_FORMAT(s_i.open_time,  '%Y-%m') AS 'mois_ouverture',
       YEARWEEK(s_i.close_time)             AS 'semaine_cloture',
       DATE_FORMAT(s_i.close_time, '%Y-%m') AS 'mois_cloture',
       p.nom,
       s.exploite_par,
       t.environnement,
       a.tdb
FROM t_link_serveur_eac t USE KEY(nna)
     INNER JOIN serveur          s    ON s.id            = t.id_serveur
     INNER JOIN plateau          p    ON p.id            = t.id_plateau
     INNER JOIN applications     a    ON a.nna           = t.nna
     INNER JOIN scope_i          s_i  USE KEY (id_serveur) ON s_i.id_serveur  = t.id_serveur
     INNER JOIN scope_i_extended s_ie USE KEY (id_scope_i) ON s_ie.id_scope_i = s_i.id
WHERE s_ie.problem_status     = 'Closed'
AND   s_ie.contact_first_name = 'AUTOMATE'
AND   s_ie.contact_last_name LIKE '%BEM%'
AND   p.id           = 4
AND   open_time >= CURDATE() - INTERVAL 52 WEEK AND open_time <= CURDATE()
AND   AND s_i.close_time < CURDATE() - INTERVAL DAYOFMONTH(CURDATE()) - 1 DAY
ORDER BY mois_cloture

当我要求mySQL解释它时,我对表s_ie的并集有一个行类型'ALL'。 我尝试创建/修改所有可能的索引,但我尝试的所有内容都没有任何区别:

id  select_type   table   type    possible_keys   key        key_len  ref                  rows   Extra
1   SIMPLE        p       const   PRIMARY         PRIMARY    4        const                 1     Using temporary; Using filesort
1   SIMPLE        a       ALL     PRIMARY         NULL       NULL     NULL                  957
1   SIMPLE        t       ref     nna             nna        26       inspire.a.nna         10    Using where
1   SIMPLE        s       eq_ref  PRIMARY         PRIMARY    4        inspire.t.id_serveur  1
1   SIMPLE        s_i     ref     id_serveur      id_serveur 4        inspire.t.id_serveur  135   Using where
1   SIMPLE        s_ie    eq_ref  id_scope_i      id_scope_i 4        inspire.s_i.id        1     Using where

s_ie有712.000行和s_i 740.000所以我认为问题来自这个结点

这是表s_ie

的结构
CREATE TABLE IF NOT EXISTS `scope_i_extended` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `id_scope_i` int(11) NOT NULL,
  `problem_status` varchar(16) NOT NULL,
  `open_group` varchar(32) NOT NULL,
  `primary_assignment` varchar(32) NOT NULL,
  `closed_by_group` varchar(32) NOT NULL,
  `contact_first_name` varchar(32) NOT NULL,
  `contact_last_name` varchar(32) NOT NULL,
  `description` text NOT NULL,
  `resolution` text NOT NULL,
  `famille_1` text NOT NULL,
  `famille_2` text NOT NULL,
  `famille_3` text NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id_scope_i` (`id_scope_i`),
  UNIQUE KEY `problem_status` (`id_scope_i`, `problem_status`, `contact_first_name`, `contact_last_name`),
  KEY `contact_last_name` (`contact_last_name`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

和s_i的结构

CREATE TABLE IF NOT EXISTS `scope_i` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `incident` varchar(20) NOT NULL,
  `statut` varchar(20) NOT NULL,
  `id_serveur` int(11) NOT NULL,
  `open_time` datetime NOT NULL,
  `close_time` datetime DEFAULT NULL,
  `affectation` varchar(50) NOT NULL,
  `titre` varchar(200) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `incident` (`incident`),
  KEY `serveur` (`id_serveur`),
  KEY `serveur_open_time` (`id_serveur`,`open_time`),
  KEY `id_serveur` (`id_serveur`,`close_time`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=738862 ;

你可以帮助/救我吗?

此致

奥利弗

2 个答案:

答案 0 :(得分:2)

很抱歉说明显而已,但我建议使用:
"YEARWEEK(open_time) <= '201246' AND YEARWEEK(open_time) >= '201146'"

而不是
"YEARWEEK(open_time) IN (...)"

IN总是让事情变得非常缓慢。

答案 1 :(得分:1)

在您的情况下,您将日期列包含在Mysql函数中。 例如:YEARWEEK(open_time)DATE_FORMAT(s_i.close_time, '%Y-%m-%d') 你应该避免这种情况,因为Mysql似乎为表的每一行执行了这个函数。

您可以尝试替换

吗?

DATE_FORMAT(s_i.close_time, '%Y-%m-%d') < DATE_FORMAT(NOW(), '%Y-%m-01')

通过

s_i.close_time < CURDATE() - INTERVAL DAYOFMONTH(CURDATE()) - 1 DAY

YEARWEEK(open_time) IN ('201246', '201245'....)

由此:(以下条件是在一年内获得所有记录的“open_time”。我不确定这是不是你的情况)

open_time >= CURDATE() - INTERVAL 1 YEAR AND open_time <= CURDATE()