【发布时间】:2012-10-26 13:58:45
【问题描述】:
我在使用 MySQL (innoDB) 5.0 时遇到了严重问题。
一个非常简单的 SQL 查询被一个非常意外的查询计划执行。
查询:
SELECT
SQL_NO_CACHE
mbCategory.*
FROM
MBCategory mbCategory
INNER JOIN ResourcePermission as rp
ON rp.primKey = mbCategory.categoryId
where mbCategory.groupId = 12345 AND mbCategory.parentCategoryId = 0
limit 20;
MBCategory - 包含 216583 行
ResourcePermission - 包含 3098354 行。
在 MBCategory 中,我有多个索引(列顺序与索引相同):
Primary (categoryId)
A (groupId,parentCategoryId,categoryId)
B (groupId,parentCategoryId)
在 ResourcePermission 中我有多个索引(列顺序与索引相同):
Primary - on some column
A (primKey).
当我查看查询计划时,Mysql 首先更改表顺序并从 ResourcePermission 中选择行,然后加入 MBCategory 表(疯狂的想法),这需要很长时间。所以我添加了STRAIGHT_JOIN 来强制innodb引擎使用正确的表序列:
SELECT
STRAIGHT_JOIN SQL_NO_CACHE
mbCategory.*
FROM
MBCategory
mbCategory
INNER JOIN ResourcePermission as rp
ON rp.primKey = mbCategory.categoryId
where mbCategory.groupId = 12345 AND mbCategory.parentCategoryId = 0
limit 20;
但是这里的第二个问题materialzie:
在我看来,mysql 应该在连接操作中使用index A (primKey),而不是对每条记录(索引映射:0x400)执行范围检查,这又需要很长时间!
强制索引没有帮助,mysql 仍在为每条记录执行 Range 检查。
MBCategory 中只有 23 行满足 where 条件,连接后只有 75 行。 我怎样才能让mysql在这个操作中选择正确的索引?
【问题讨论】:
-
我认为 MySQL 无法直接确定它必须读取多少行才能找到 20 个匹配的行;因此,它为 20 个匹配项选择较大的表,然后执行内部连接。如果取消限制会怎样?
-
删除限制不会改变任何事情。我只需要 mysql 使用正确的索引而不是范围检查
标签: mysql indexing range inner-join