Mysql范围检查而不是内连接上的索引用法

时间:2012-11-06 15:18:54

标签: mysql indexing range inner-join

我遇到了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;

但这里的第二个问题是材料: 在我看来,mysql应该在连接操作上使用index A (primKey),而不是为每条记录执行Range检查(索引图:0x400),它再次需要很长时间! 强制索引没有帮助,mysql仍在为每条记录执行Range检查。

MBCategory中只有23行符合标准,加入后只有75行。 如何让mysql在此操作中选择正确的索引?

2 个答案:

答案 0 :(得分:29)

确定, 基本问题。 我欠自己一杯啤酒。 我最近调整的系统不是我开发的系统 - 我的管理层已将其分配给我以提高性能(原创团队对此主题没有了解)。

经过几周的改进SQL查询,索引,应用程序正在执行的SQL查询数量,我没有检查这个案例中最重要的事情之一!!

列类型不同!

开发人员编写的代码应该是一个很大的代码。

感谢您的帮助!

答案 1 :(得分:0)

我有相同的问题,原因不同。我正在加入一个大表,并且ON子句使用OR将主键(ii.itemid)与两个不同的列进行比较:

SELECT *
FROM share_detail sd
JOIN box_view bv ON sd.container_id = bv.id
JOIN boxes b ON b.id = bv.shared_id
JOIN item_index ii ON ii.itemid = bv.shared_id OR b.parent_itemid = ii.itemid;

幸运的是,事实证明parent_itemid比较是多余的,因此我能够将其删除。现在正在按预期使用索引。否则,我将尝试将item_index连接拆分为两个单独的连接。