2017-08-07 29 views
2

我的代码有趣的MySQL 5.6的行为

SELECT candidate.ID 
FROM users u 
JOIN users candidate ON candidate.a = u.a AND candidate.b < 1 
JOIN user_meta meta ON candidate.id = meta.user_id 
WHERE u.id = 1 
AND candidate.count > 0 
ORDER BY meta.updated_at DESC 
LIMIT 100 

这短短的片段,并在其周围,我认为是远远慢,所以我开始去查了一下787-8结束英寸我尝试了加入条件的实验

SELECT candidate.ID 
FROM users u 
JOIN users candidate ON candidate.a = u.a AND candidate.b < 2 
JOIN user_meta meta ON candidate.id = meta.user_id 
WHERE u.id = 1 
AND candidate.count > 0 
ORDER BY meta.updated_at DESC 
LIMIT 100 

并且有趣的是它在80ms内完成。唯一改变的是小于1至小于2

运行EXPLAIN的查询产生以下两个查询

id select_type table  type possible_keys key      key_len ref    rows Extra 
1 SIMPLE  u   const PRIMARY,index_a PRIMARY     4  const   1 NULL 
1 SIMPLE  meta  index PRIMARY   index_meta_on_updated_at 5  NULL   100 Using index 
1 SIMPLE  candidate eq_ref PRIMARY,index_a PRIMARY     4  db.meta.user_id 1 Using where 

也许不是我错过了什么,但可能导致此行为?

+2

对于'candidate.b <1'有多少条记录,以及'candidate.b <2'有多少条记录?做一个单独的查询来找出。您还可以使用'EXPLAIN EXTENDED'和[SHOW _PROFILE](https://dev.mysql.com/doc/refman/5.5/en/show-profile.html)来获取关于MySQL幕后操作的详细信息。 'SHOW PROFILE'会给你详细的信息和时间,每个步骤MySQL执行查询(打开表格,搜索索引或磁盘,通过网络发送等) – Mjh

+3

如果您使用innodb它可能是表( s)在innodb缓冲区(RAM内存)中,因为您执行了第一个查询。可以理解为什么第二个查询执行得更快.. –

+0

关于@RaymondNijland评论,我总是使用'SQL_NO_CACHE'来尝试和帮助比较苹果与苹果,当调查这样的“问题” - 但它不会帮助Innodb缓冲区。 – wally

回答

0

你能提供有关的更多信息: - 表(可以使用说明) - 有多少条记录已经每张桌子 - 是否有表索引?

对于疑难解答,您可以在MySQL中使用像Mjh告诉你的解释。为我们提供每个查询的解释,这将有助于我们为您提供更好的建议,甚至帮助您更好地进行查询。

+0

这是适当的(并有帮助)作为对问题的评论,但不作为答案。我会把它移到那里。 – wally

+1

由于我不能添加评论,我不得不将它作为一个问题。@ wally – Noob

+0

啊,是的,道歉 - 我总是忘记SO力量。 (这已经很长时间了,因为它影响了我。)说实话,这感觉就像是在惩罚新用户,但我想必须有一个折中的地方! – wally