我在优化这个需要13s的查询时遇到了问题
SELECT `user_id`,`op`, COUNT(*) AS `count` FROM `imported_customer`
WHERE (`id` IN (
SELECT `imported_customer_id` FROM `history`
WHERE `date` < NOW() - INTERVAL 10 DAY
GROUP BY `imported_customer_id`
HAVING MAX(`event_type_id`)= 2
)
)
GROUP BY `op`
ORDER BY `user_id`, `op`
说明:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY imported_customer index op 35 1718 Using where; Using temporary; Using filesort
2 DEPENDENT SUBQUERY history index imported_customer_id 8 2 Using where
子查询很好,它在38ms运行,并且运算符的结果列表是300个数字,这应该没问题。
所以唯一依赖的是count(*),在主查询中使用GROUP和ORDER。
解释该查询告诉&#34;使用where;使用临时;使用filesort&#34;,这是错误的优化查询的标志。
在表上,imported_customer是id,user_id和op。
的索引但查询仍然很慢,如何优化呢?
SQLFiddle:http://sqlfiddle.com/#!9/02d37/2/0 - (查询中未使用的列未包括在内)由于数据量少而速度快但解释看起来相同
答案 0 :(得分:1)
我认为你可以尝试在你的表imported_customer:
上添加这样的索引INDEX `test2` (`user_id`,`op`)
然后使用
group by (`user_id`,`op`)
答案 1 :(得分:1)
您可以尝试将WHERE ... IN ()
替换为JOIN
,如此(http://sqlfiddle.com/#!9/3bb51/1/0):
SELECT user_id,op, COUNT(*) AS count
FROM imported_customer i
JOIN (
SELECT imported_customer_id
FROM history
WHERE `date` < NOW() - INTERVAL 10 DAY
GROUP BY imported_customer_id
HAVING MAX(event_type_id)= 2
) h ON i.id = h.imported_customer_id
GROUP BY user_id, op
ORDER BY user_id, op
您应该考虑在历史记录表中使用覆盖索引(date, imported_customer_id, event_type_id)
来帮助生成按日期过滤的聚合。
出于同样的原因,您应该考虑在导入的客户表上使用复合索引(id, user_id, op)
。
请注意,SQL Fiddle中的索引选择可能与扩展查询中的索引选择不同。
另请注意,您使用并可能滥用了GROUP BY
的有害MySQL扩展。
不要被“使用临时;使用filesort”困惑。您在外部查询中执行的聚合计算类型需要这些操作。 Filesort并不总是意味着真实的文件;它可以指内存中间结果的排序。你是正确的,“使用where”并不是良好优化的标志。