MySQL 5.5.28。我有两个表Person
,Message
后者有一个外键。每个表都有id
一个主键列,并且该Person
表还有一个personId
(唯一)索引的列。
下面的查询应该利用personId
键索引,但 MySQLMessage
出于某种原因需要扫描整个表:
mysql> 解释 SELECT `m`.* -> 从 -> `消息`作为`m` -> 左连接 -> `Person` AS `p` ON (`m`.`person` = `p`.`id`) -> 在哪里 -> 'M002649397' 为空或 -> `p`.`personId` = 'M002649397'; +----+-------------+--------+--------+------------- --+---------+---------+----------------+--------+- ------------+ | 编号 | 选择类型 | 表| 类型 | 可能的键 | 关键 | key_len | 参考 | 行 | 额外 | +----+-------------+--------+--------+------------- --+---------+---------+----------------+--------+- ------------+ | 1 | 简单 | 米 | 全部 | 空 | 空 | 空 | 空 | 273220 | | | 1 | 简单 | p | eq_ref | 初级 | 初级 | 8 | pcom.m.人 | 1 | 使用位置 | +----+-------------+--------+--------+------------- --+---------+---------+----------------+--------+- ------------+ 2 行(0.00 秒)
但是当我注释掉'M002649397' IS NULL OR
子句(对结果没有影响)时,查询突然变得更有效率:
mysql> 解释 SELECT `m`.* -> 从 -> `消息`作为`m` -> 左连接 -> `Person` AS `p` ON (`m`.`person` = `p`.`id`) -> 在哪里 -> -- 'M002649397' 为空或 -> `p`.`personId` = 'M002649397'; +----+-------------+--------+-------+-------------- ------+--------+---------+--------+---- --+--------------+ | 编号 | 选择类型 | 表| 类型 | 可能的键 | 关键 | key_len | 参考 | 行 | 额外 | +----+-------------+--------+-------+-------------- ------+--------+---------+--------+---- --+--------------+ | 1 | 简单 | p | 常量 | PRIMARY,personId | 人名 | 第767章 常量 | 1 | 使用索引 | | 1 | 简单 | 米 | 参考 | FK9C2397E7A0F6ED11 | FK9C2397E7A0F6ED11 | 9 | 常量 | 3 | 使用位置 | +----+-------------+--------+-------+-------------- ------+--------+---------+--------+---- --+--------------+ 2 行(0.01 秒)
我的问题是:为什么 MySQL 不够聪明,无法意识到这'M002649397' IS NULL
总是错误的,优化它,省去不必要地扫描大表中的每一行?
换句话说,MySQL 优化器是否不知道它'M002649397' IS NULL
总是错误的,或者它在构建其查询计划时未能将该优化应用于查询?