MySQL 5.5.28. I have two tables Person and Message , and the latter has a foreign key for the first. Each table has id as the primary key column, and the Person table also has a personId column that is indexed (uniquely).
The query below should use the personId key personId , but instead, MySQL requires scanning the entire Message table for some reason:
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)
But when I comment on the sentence 'M002649397' IS NULL OR (which does not affect the result), the request suddenly becomes more efficient:
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)
My question is: why is MySQL not smart enough to understand that the 'M002649397' IS NULL always false, optimizes it, and saves the need to flawlessly scan each row in a huge table?
In other words, does the MySQL optimizer not know that the 'M002649397' IS NULL always false, or cannot it apply this optimization to the query when building its query plan?
source share