我的表格如下:
`MyDB`.`Details` (
`id` bigint(20) NOT NULL,
`run_id` int(11) NOT NULL,
`element_name` varchar(255) NOT NULL,
`value` text,
`line_order` int(11) default NULL,
`column_order` int(11) default NULL
);
我在存储过程中有以下SELECT语句
SELECT
RULE
,TITLE
,SUM(IF(t.PASSED='Y',1,0)) AS PASS
,SUM(IF(t.PASSED='N',1,0)) AS FAIL
FROM
(
SELECT
a.line_order
,MAX(CASE WHEN a.element_name = 'PASSED' THEN a.`value` END) AS PASSED
,MAX(CASE WHEN a.element_name = 'RULE' THEN a.`value` END) AS RULE
,MAX(CASE WHEN a.element_name = 'TITLE' THEN a.`value` END) AS TITLE
FROM
Details a
WHERE
run_id = runId
GROUP BY line_order
) t
GROUP BY RULE, TITLE;
* runId是存储过程的输入参数。
此查询大约需要14秒才能运行。该表有214856行,我正在过滤的特定run_id有162204条记录。它不是超级大功率机器,但我觉得我可以更有效地做到这一点。我的主要目标是按规则和标题进行汇总,并显示通过和失败计数列。
表创建脚本:
CREATE TABLE `MyDB`.`Details` (
`id` bigint(20) NOT NULL,
`run_id` int(11) NOT NULL,
`element_name` varchar(255) NOT NULL,
`value` text,
`line_order` int(11) default NULL,
`column_order` int(11) default NULL,
KEY `report_id` (`run_id`),
KEY `element_name` (`element_name`),
CONSTRAINT `Details_ibfk_1` FOREIGN KEY (`run_id`) REFERENCES `RunHistory` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
解释:
select `t`.`RULE` AS `RULE`,`t`.`TITLE` AS `TITLE`,sum(if((`t`.`PASSED` = _utf8'Y'),1,0)) AS `PASS`,sum(if((`t`.`PASSED` = _utf8'N'),1,0)) AS `FAIL` from (select `TAA`.`Details`.`line_order` AS `line_order`,max((case when (`TAA`.`Details`.`element_name` = _utf8'PASSED') then `TAA`.`Details`.`value` end)) AS `PASSED`,max((case when (`TAA`.`Details`.`element_name` = _utf8'RULE') then `TAA`.`Details`.`value` end)) AS `RULE`,max((case when (`TAA`.`Details`.`element_name` = _utf8'TITLE') then `TAA`.`Details`.`value` end)) AS `TITLE` from `TAA`.`Details` where (`TAA`.`Details`.`run_id` = 66) group by `TAA`.`Details`.`line_order`) `t` group by `t`.`RULE`,`t`.`TITLE`
id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra
1, 'PRIMARY', '<derived2>', 'ALL', '', '', '', '', 3068, 'Using temporary; Using filesort'
2, 'DERIVED', 'Details', 'ref', 'report_id', 'report_id', '4', '', 107563, 'Using where; Using temporary; Using filesort'
答案 0 :(得分:3)
哇。以下是一些提示:
答案 1 :(得分:2)
如果您可以将数据从属性值方法中规范化并避免转换它们,那么最大的收获就是。你能这样做吗?
您还可以在详细信息中显示SHOW INDEXES吗?
编辑: 似乎新的索引建议对你有用。你能满足我的好奇心并检查两件事:
以下是对聚合转换为连接的查询的重写,您能检查它与原始连接的比较吗?
SELECT
RULE
,TITLE
,SUM(IF(t.PASSED='Y',1,0)) AS PASS
,SUM(IF(t.PASSED='N',1,0)) AS FAIL
FROM
(
SELECT
a.line_order,
a.value AS TITLE,
b.value AS RULE,
c.value AS PASSED
FROM
Details a INNER JOIN
Details b ON a.line_order = b.line_order AND a.run_id = runId AND a.element_name = 'PASSED' INNER JOIN
Details c ON b.line_order = c.line_order AND b.run_id = runId AND b.element_name = 'RULE' AND c.element_name = 'TITLE'
) t
GROUP BY RULE, TITLE;
关于加入的一些注释
最后,如果你在('run_id','line_order','element_name','value')上添加索引,你还能检查你的查询速度会发生什么变化吗?我不确定它会改进什么(它会增加索引的大小,但会削减对各行的访问权限),所以查看数字会很有意思(检查计划是否真的使用它)。
最后,关于原始查询的另一个注释 - 可能至少在一个步骤中进行聚合。你想进一步调查吗?