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;
しかし、ここで2番目の問題Materialzie:私の意見では、mysqlはindex A (primKey)
代わりに結合操作で使用する必要があり、各レコード(インデックスマップ:0x400)の範囲チェックを実行し、再び時間がかかります!Force index は役に立たず、mysql はまだ各レコードに対して Range checked を実行しています。
MBCategory には where 基準を満たす行が 23 行しかなく、結合後は 75 行しかありません。この操作でmysqlに正しいインデックスを選択させるにはどうすればよいですか?