如果我运行以下查询,每个查询都会快速返回(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.workcode
,worktag.tagId
,tag.tagId
和tag.name
的索引。
如果我在查询上运行DESCRIBE
,前两个使用索引,第二个使用索引作为子查询(在tag
表上),但不使用{ {1}}表。
有谁知道为什么会这样?
注意:worktag
表中有超过1800万条记录。
答案 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)
我猜优化器做了一些糟糕的猜测。用内连接替换查询可能会有所帮助。