0

我有一个使 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 ;

你能帮我/救我吗?

问候,

奥利维尔

4

2 回答 2

2

很抱歉说明了这一点,但我建议使用:
"YEARWEEK(open_time) <= '201246' AND YEARWEEK(open_time) >= '201146'"

代替
"YEARWEEK(open_time) IN (...)"

IN 总是显着减慢速度。

于 2012-11-15T10:46:39.643 回答
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()

于 2012-11-15T12:16:59.887 回答