- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
MySQL 5.5.28。我有两个表 Person
和 Message
,后者有前者的外键。每个表都有 id
作为主键列,Person
表还有一列 personId
,它是(唯一)索引的。
下面的查询应该利用 personId
键索引,但是 MySQL 出于某种原因需要扫描整个 Message
表:
mysql> EXPLAIN SELECT `m`.* -> FROM -> `Message` AS `m` -> LEFT JOIN -> `Person` AS `p` ON (`m`.`person` = `p`.`id`) -> WHERE -> 'M002649397' IS NULL OR -> `p`.`personId` = 'M002649397';+----+-------------+-------+--------+---------------+---------+---------+----------------+--------+-------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+-------+--------+---------------+---------+---------+----------------+--------+-------------+| 1 | SIMPLE | m | ALL | NULL | NULL | NULL | NULL | 273220 | || 1 | SIMPLE | p | eq_ref | PRIMARY | PRIMARY | 8 | pcom.m.person | 1 | Using where |+----+-------------+-------+--------+---------------+---------+---------+----------------+--------+-------------+2 rows in set (0.00 sec)
但是当我注释掉 'M002649397' IS NULL OR
子句(对结果没有影响)时,查询突然变得更加高效:
mysql> EXPLAIN SELECT `m`.* -> FROM -> `Message` AS `m` -> LEFT JOIN -> `Person` AS `p` ON (`m`.`person` = `p`.`id`) -> WHERE -> -- 'M002649397' IS NULL OR -> `p`.`personId` = 'M002649397';+----+-------------+-------+-------+--------------------+--------------------+---------+-------+------+-------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+-------+-------+--------------------+--------------------+---------+-------+------+-------------+| 1 | SIMPLE | p | const | PRIMARY,personId | personId | 767 | const | 1 | Using index || 1 | SIMPLE | m | ref | FK9C2397E7A0F6ED11 | FK9C2397E7A0F6ED11 | 9 | const | 3 | Using where |+----+-------------+-------+-------+--------------------+--------------------+---------+-------+------+-------------+2 rows in set (0.01 sec)
我的问题是:为什么 MySQL 不够聪明,无法意识到 'M002649397' IS NULL
始终为 false,将其优化掉,从而避免不必要地扫描巨大表中的每一行?
换句话说,MySQL 优化器是否不知道 'M002649397' IS NULL
始终为 false,或者它是否在构建查询计划时未能将优化应用于查询?
最佳答案
实际上,更有趣的是文档说 MySQL 足够智能来执行此操作(参见 here)。
这似乎在标题“8.2.1.2. 消除“死”代码”下。
我想原因是开发人员在编写代码时没有考虑诸如“is not null”之类的表达式。该文档给出了许多基于常量传播的示例(x1 = 2 and x2 = x1
变为 x1 = 2 and x2 = 2
)。 is null
可能确实出现在这种情况下。
关于MySQL:为什么 'FOO' IS NULL 没有被优化掉?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16848190/
我正在编写一个快速的 preg_replace 来从 CSS 中删除注释。 CSS 注释通常有这样的语法: /* Development Classes*/ /* Un-comment me for
使用 MySQL,我有三个表: 项目: ID name 1 "birthday party" 2 "soccer match" 3 "wine tasting evening" 4
我是一名优秀的程序员,十分优秀!