Description:
'not exists' optimization for outer joins and VARCHAR column doesn't work:
mysql> show create table imagelinks;
+------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| imagelinks | CREATE TABLE `imagelinks` (
`il_from` int(10) unsigned NOT NULL default '0',
`il_to` varchar(255) character set latin1 collate latin1_bin NOT NULL default '',
`img_id` int(11) default NULL,
UNIQUE KEY `il_from` (`il_from`,`il_to`),
KEY `il_to` (`il_to`,`il_from`),
KEY `img_id` (`img_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.04 sec)
mysql> show create table page_associate_image;;
+----------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+----------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| page_associate_image | CREATE TABLE `page_associate_image` (
`page_id` int(8) NOT NULL,
`img_name` varchar(255) NOT NULL,
`img_id` int(11) default NULL,
KEY `page_id` (`page_id`),
KEY `IDX_page_associate_image_img_name` (`img_name`),
KEY `img_name` (`img_name`(10)),
KEY `img_id` (`img_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 |
+----------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> select * from page_associate_image;
+------------+----------+--------+
| page_id | img_name | img_id |
+------------+----------+--------+
| -634462102 | iii | 1 |
| -597187184 | iii | 1 |
| -821211600 | iii | 1 |
| 0 | iii | 1 |
| -566146336 | iii | 1 |
+------------+----------+--------+
5 rows in set (0.09 sec)
mysql> select * from imagelinks;
+------------+-------+--------+
| il_from | il_to | img_id |
+------------+-------+--------+
| 2056786463 | iii | 1 |
| 2066518885 | iii | 1 |
| 2066783021 | iii | 1 |
| 2091789635 | iii | 1 |
| 2102645533 | iii | 1 |
+------------+-------+--------+
5 rows in set (0.00 sec)
mysql> EXPLAIN SELECT i.il_from, i.il_to FROM imagelinks i LEFT JOIN page_associate_image pai ON i.il_to = pai.img_name WHERE pai.img_name IS NULL\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: i
type: index
possible_keys: NULL
key: img_id
key_len: 5
ref: NULL
rows: 5
Extra: Using index
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: pai
type: index
possible_keys: IDX_page_associate_image_img_name,img_name
key: IDX_page_associate_image_img_name
key_len: 257
ref: NULL
rows: 5
Extra: Using where; Using index; Not exists
2 rows in set (0.00 sec)
But with INTEGER columns optimization works:
mysql> EXPLAIN SELECT i.il_from, i.il_to FROM imagelinks i LEFT JOIN page_associate_image pai ON i.img_id = pai.img_id WHERE pai.img_name IS NULL\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: i
type: index
possible_keys: NULL
key: img_id
key_len: 5
ref: NULL
rows: 5
Extra: Using index
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: pai
type: ref
possible_keys: img_id
key: img_id
key_len: 5
ref: issue22635.i.img_id
rows: 2
Extra: Using where; Not exists
2 rows in set (0.01 sec)
How to repeat:
--source include/have_innodb.inc
--disable_result_log
--disable_query_log
DROP TABLE IF EXISTS `page_associate_image`;
CREATE TABLE `page_associate_image` (
`page_id` int(8) NOT NULL,
`img_name` varchar(255) NOT NULL,
`img_id` int(11) default NULL,
KEY `page_id` (`page_id`),
KEY `IDX_page_associate_image_img_name` (`img_name`),
KEY `img_name` (`img_name`(10)),
KEY `img_id` (`img_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO `page_associate_image` VALUES (-634462102,'iii',1),(-597187184,'iii',1),(-821211600,'iii',1),(0,'iii',1),(-566146336,'iii',1);
DROP TABLE IF EXISTS `imagelinks`;
CREATE TABLE `imagelinks` (
`il_from` int(10) unsigned NOT NULL default '0',
`il_to` varchar(255) character set latin1 collate latin1_bin NOT NULL default '',
`img_id` int(11) default NULL,
UNIQUE KEY `il_from` (`il_from`,`il_to`),
KEY `il_to` (`il_to`,`il_from`),
KEY `img_id` (`img_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `imagelinks` VALUES (2056786463,'iii',1),(2066518885,'iii',1),(2066783021,'iii',1),(2091789635,'iii',1),(2102645533,'iii',1);
--enable_query_log
--enable_result_log
EXPLAIN SELECT i.il_from, i.il_to
FROM imagelinks i
LEFT JOIN page_associate_image pai
ON i.il_to = pai.img_name
WHERE pai.img_name IS NULL;
EXPLAIN SELECT i.il_from, i.il_to
FROM imagelinks i
LEFT JOIN page_associate_image pai
ON i.img_id = pai.img_id
WHERE pai.img_name IS NULL;
Suggested fix:
Don't scan all rows to output 0 rows