为什么这个简单的SQL查询会导致简单的6k记录表出现严重滞后?

时间:2013-07-14 06:10:12

标签: mysql sql database debugging query-optimization

所以我有2个表,一个叫user,一个叫user_favoriteuser_favorite存储itemIduserId,用于存储用户已收藏的项目。我只是想找到user_favorite中有记录的用户,这样我就可以找到那些尚未收藏任何内容的用户。

出于测试目的,我在user中有6001条记录,在user_favorite中有6001条记录,所以只有一条记录没有任何收藏。

这是我的疑问:

  SELECT u.* FROM user u
   JOIN user_favorite fav ON u.id != fav.userId
   ORDER BY id DESC

这里最后一个语句中的id不是ambigious,它指的是user表中的id。我在u.id上有一个PK索引,在fav.userId上有一个索引。

当我运行此查询时,我的计算机变得没有响应并完全冻结,没有给出任何输出。我有2GB的RAM,不是一台好的计算机,但我认为它应该能够轻松处理6k记录这样的查询。

这两个表都在MyISAM中,这可能是问题吗?转换到INNODB会修复吗?

3 个答案:

答案 0 :(得分:3)

让我们首先讨论您的查询(正如所写)正在做什么。由于on-子句中的!=,您将使用其他每个用户的收藏夹加入每个用户记录。因此,您的查询将生成类似36M行的内容。这不会给你你想要的答案。它解释了为什么你的电脑不满意。

您应该如何编写查询?您可以使用三种主要模式。我认为这是一个非常好的解释:http://explainextended.com/2009/09/18/not-in-vs-not-exists-vs-left-join-is-null-mysql/并且特别在mysql的上下文中讨论了性能。它向您展示了如何查看和阅读执行计划,这对优化查询至关重要。

答案 1 :(得分:1)

将您的查询更改为以下内容:

select * from User 
where not exists (select * from user_favorite where User.id = user_favorite.userId)

让我知道它是怎么回事

答案 2 :(得分:1)

A != B上的联接意味着A的每个记录都与B的每个记录连接在一起,其中id不相等。

换句话说,不是产生6000行,而是产生大约3600万(6000 * 6001)行的输出,所有这些都必须被收集,然后排序......