我在Debian 8机器上使用mysql 5.5.52,有时我们的查询速度慢(> 3s),通常花费0.1s。我已经开始使用explain命令来查找正在发生的事情。
这是查询和解释信息
explain
SELECT
`box`.`message_id` ID
, `messages`.`tipo`
, `messages`.`text`
, TIME_TO_SEC(TIMEDIFF(NOW(), `messages`.`date`)) `date`
FROM (`box`)
INNER JOIN `messages` ON `messages`.`id` = `box`.`message_id`
WHERE `box`.`user_id` = '1010231' AND `box`.`deleted` = 0
AND `messages`.`deleted` = 0
AND `messages`.`date` + INTERVAL 10 MINUTE > NOW()
ORDER BY `messages`.`id` ASC LIMIT 100;
id| select_type| table | type | possible_keys | key | key_len| ref | rows | Extra
1|SIMPLE |box |ref |user_id,message_id|user_id| 4|const | 2200 |Using where; Using temporary; Using filesort
1|SIMPLE |messages|eq_ref|PRIMARY |PRIMARY| 4|box.message_id| 1 |Using where
我知道临时表和filesort是一件坏事,我想问题是订单键不属于查询中的第一个表(框)并将其更改为box.message_id,解释信息是
id,select_type,table,type,possible_keys,key,key_len,ref,rows,Extra
1 SIMPLE框索引user_id,message_id message_id 4 443使用位置
1个SIMPLE消息eq_ref PRIMARY PRIMARY 4 box.message_id 1使用地点
它看起来更好,但我不明白为什么它使用message_id索引,最糟糕的是,现在查询需要1.5s而不是初始0.1s
编辑:
强制查询使用user_id索引,我得到与初始查询相同的结果(0.1s),但没有临时
explain
SELECT
`box`.`message_id` ID
, `messages`.`tipo`
, `messages`.`text`
, TIME_TO_SEC(TIMEDIFF(NOW(), `messages`.`date`)) `date`
FROM (`box` use index(user_id) )
INNER JOIN `messages` ON `messages`.`id` = `box`.`message_id`
WHERE `box`.`user_id` = '1010231' AND `box`.`deleted` = 0
AND `messages`.`deleted` = 0
AND `messages`.`date` + INTERVAL 10 MINUTE > NOW()
ORDER BY `box`.`message_id` ASC LIMIT 100;
id| select_type| table | type | possible_keys | key | key_len| ref | rows | Extra
1|SIMPLE |box |ref |user_id,message_id|user_id| 4|const | 2200 |Using where; Using filesort
1|SIMPLE |messages|eq_ref|PRIMARY |PRIMARY| 4|box.message_id| 1 |Using where
我认为跳过临时是比初始查询更好的解决方案,下一步是检查组合索引为ysth推荐。
答案 0 :(得分:0)
计算要比较的字段值不是一个好主意。然后你得到一个完整的表扫描。 MySQL必须先为每个ROW执行此操作才能检查条件。在恒定的条件下做它更好。然后MySQL可以使用索引(如果在此字段中有一个)
从
更改AND messages.date + INTERVAL 10 MINUTE > NOW()
到
AND messages.date > NOW() - INTERVAL 10 MINUTE
答案 1 :(得分:0)
此处的临时和文件排序不不好;它们是必需的,因为使用最佳索引(user_id)并不能自然地生成按照您要求的顺序排序的记录。
使用组合的user_id,message_id索引可能会做得更好,但这可能也会变得更糟。取决于您的确切数据。
如果您发现某些用户ID的查询时间较长或相同的用户ID有时会花费更长时间,则我不清楚。
更新:似乎将组合索引和更改顺序更改为box.user_id,box.message_id将解决您的问题,至少对于没有大量已删除邮件的用户而言。