我试图使以下查询运行速度超过180秒:
SELECT
x.di_on_g AS deviceid, SUM(1) AS amount
FROM
(SELECT
g.device_id AS di_on_g
FROM
guide g
INNER JOIN operator_guide_type ogt ON ogt.guide_type_id = g.guide_type_id
INNER JOIN operator_device od ON od.device_id = g.device_id
WHERE
g.operator_id IN (1 , 1)
AND g.locale_id = 1
AND (g.device_id IN ("many (~1500) comma separated IDs coming from my code"))
GROUP BY g.device_id , g.guide_type_id) x
GROUP BY x.di_on_g
ORDER BY amount;
来自EXPLAIN的屏幕截图: https://ibb.co/da5oAF
即使我将子查询作为单独的查询运行,它仍然非常慢......:
SELECT
g.device_id AS di_on_g
FROM
guide g
INNER JOIN operator_guide_type ogt ON ogt.guide_type_id = g.guide_type_id
INNER JOIN operator_device od ON od.device_id = g.device_id
WHERE
g.operator_id IN (1 , 1)
AND g.locale_id = 1
AND (g.device_id IN (("many (~1500) comma separated IDs coming from my code")
EXPLAIN:
的屏幕截图ibb.co/gJHRVF
我在g.device_id
和其他适当的地方都有索引。
索引:
SHOW INDEX FROM guide;
ibb.co/eVgmVF
SHOW INDEX FROM operator_guide_type;
ibb.co/f0TTcv
SHOW INDEX FROM operator_device;
ibb.co/mseqqF
我尝试为ID创建一个新的临时表,并使用JOIN
替换慢IN clause
,但这不会使查询更快。
所有ID都是整数,我尝试为来自我的代码和JOIN表的id创建一个新的临时表而不是慢速的IN子句,但这并没有使查询更快。 (快10秒)
没有一个表有超过300,000行,而且mysql配置也不错。
视觉计划: Query Plan
任何帮助将不胜感激!
答案 0 :(得分:0)
让我们关注子查询。主要的问题是" inflate-deflate",但我马上就会谈到它。
添加综合索引:
INDEX(locale_id, operator_id, device_id)
为什么重复" 1"在
g.operator_id IN (1 , 1)
为什么GROUP BY
有2列,只选择1?是否有使用GROUP BY
代替DISTINCT
的原因。 (后者似乎是你的意图。)
这些
的唯一原因INNER JOIN operator_guide_type ogt ON ogt.guide_type_id = g.guide_type_id
INNER JOIN operator_device od ON od.device_id = g.device_id
将验证其他表中是否有指南和设备。那是对的吗?这些是PRIMARY KEYs
,因此是唯一的吗?:ogt.guide_type_id
和od.device_id
。如果是这样,为什么需要GROUP BY
?基于EXPLAIN
,听起来这两者都是相关的1:很多。所以......
SELECT g.device_id AS di_on_g
FROM guide g
WHERE EXISTS( SELECT * FROM operator_guide_type WHERE guide_type_id = g.guide_type_id )
AND EXISTS( SELECT * FROM operator_device WHERE device_id = g.device_id
AND g.operator_id IN (1)
AND g.locale_id = 1
AND g.device_id IN (...)
注意:
GROUP BY
。JOIN
+ GROUP BY
已消失。解释指出了这一点 - 139K行充气至61M - 非常昂贵。EXISTS
是" semijoin",表示它不会收集所有匹配,但会在找到任何匹配时停止。 " mysql配置很好" - 你有多少RAM?桌子是什么引擎? innodb_buffer_pool_size
的价值是什么?