【问题标题】:MySQL: why isn't 'FOO' IS NULL optimized away?MySQL:为什么不优化'FOO'IS NULL?
【发布时间】:2013-05-26 17:42:57
【问题描述】:
MySQL 5.5.28。我有两个表Person 和Message,后者有一个外键到前者。每个表都有id 作为主键列,Person 表还有一个列personId,它是(唯一)索引的。
下面的查询应该利用 personId 键索引,但 MySQL 出于某种原因需要扫描整个 Message 表:
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 始终为假,或者它在构造查询计划时未能将该优化应用于查询?
【问题讨论】:
-
也许查询计划器不是这样设计的,因为他们希望开发人员不要编写我们可以轻松手动优化的查询?在查询中甚至有这个条件似乎有点傻。一个更好的问题可能是,“我为什么要在我的查询中使用这个?我能找到更好的方法来生成查询吗?”如果您正在生成查询代码端,那么您应该能够省略条件。
-
-
-
如果将where子句更改为WHERE 0 or `p`.`personId` = 'M002649397'会发生什么
-
我想知道如果IS NULL被任何其他常量表达式替换,结果是否相同。
标签:
mysql