我有一个使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 ;
你可以帮助/救我吗?
此致
奥利弗
答案 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()