使用IN谓词的MySQL性能

时间:2009-10-09 20:15:26

标签: sql mysql performance

如果我运行以下查询,每个查询都会快速返回(0.01秒)并给出我想要的结果。

SELECT tagId FROM tag WHERE name='programming'

SELECT COUNT(DISTINCT workcode) FROM worktag WHERE tagId=123 OR tagId=124

(假设两个tagId数字是第一个查询的结果)

我想结合这些查询,所以我只需要运行一次:

SELECT COUNT(DISTINCT workcode) FROM worktag WHERE tagId IN (SELECT tagId FROM tag WHERE name='programming')

然而,此查询在大约1分钟和20秒内完成。我有worktag.workcodeworktag.tagIdtag.tagIdtag.name的索引。

如果我在查询上运行DESCRIBE,前两个使用索引,第二个使用索引作为子查询(在tag表上),但不使用{ {1}}表。

有谁知道为什么会这样?

注意:worktag表中有超过1800万条记录。

6 个答案:

答案 0 :(得分:2)

为什么不使用连接而不是子查询?

SELECT COUNT(DISTINCT workcode)
FROM worktag
LEFT JOIN tag
  ON worktag.tagId = tag.tagID
WHERE tag.name = 'programming'

P.S。:似乎是reported as bug

答案 1 :(得分:1)

数据库管理员最近告诉我,语法WHERE x IN ( ... )对数据库来说很痛苦。联接几乎总是更好:

SELECT COUNT(DISTINCT wt.workcode) 
  FROM worktag wt, tag t 
 WHERE wt.tagId = t.tagId 
   AND t.name='programming'

答案 2 :(得分:1)

SELECT COUNT(DISTINCT workcode) 
FROM worktag 
inner join tag on worktag.tagid = tag.tagid
WHERE tag.name='programming'

答案 3 :(得分:1)

MySQL通常不能很好地处理子查询,甚至是独立查询。讨论联接的海报是对的 - 如果你有选择,可以使用联接。如果你不能轻易使用连接(即foo.x in(从y中选择y,其中y = xxx limit 10)),最好将限制运行到临时的IN MEMORY表中并使用连接就可以了

如果您经常使用MySQL,请使用EXPLAIN,您将看到它是如何使用索引等的。

答案 4 :(得分:0)

你试过了吗?

SELECT COUNT(DISTINCT workcode) FROM worktag WHERE tagId IN (123, 124)

我不是MySQL专家,但在我看来,您可能正在查看查询优化器的重大故障。

另一方面,对MySQL有利,它优化了第二个语句中的OR。我知道将成功优化IN()的数据库,但不知道同一逻辑请求的OR版本。

答案 5 :(得分:0)

我猜优化器做了一些糟糕的猜测。用内连接替换查询可能会有所帮助。