我遇到了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在此操作中选择正确的索引?
答案 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连接拆分为两个单独的连接。