Description:
Optimizer uses complex index in a single-table query with constants:
mysql> explain select count(*) from item where productcode = 'ZQXW0' and customerspecific=0 and color='500' and dataformat='FP1';
+----+-------------+-------+------+--------------------------------------------+
----------+---------+-------------------+------+-------------+
| id | select_type | table | type | possible_keys |
key | key_len | ref | rows | Extra |
+----+-------------+-------+------+--------------------------------------------+
----------+---------+-------------------+------+-------------+
| 1 | SIMPLE | item | ref | item_1,item_5,Item_color,complex1,complex2 |
complex1 | 1537 | const,const,const | 1 | Using where |
+----+-------------+-------+------+--------------------------------------------+
----------+---------+-------------------+------+-------------+
1 row in set (0.00 sec)
But does not use the same index when 2 of those columns are joined to the other table:
mysql> select count(*) from product;
+----------+
| count(*) |
+----------+
| 746 |
+----------+
1 row in set (0.00 sec)
mysql> select count(*) from item, product
-> where
-> item.customerspecific = 0 and
-> item.color = product.maincolor and
-> item.dataformat = 'FP1' and
-> item.productcode = product.code;
+----------+
| count(*) |
+----------+
| 61 |
+----------+
1 row in set (0.02 sec)
mysql> explain select count(*) from item, product where item.customerspecific = 0 and item.color = product.maincolor and item.dataformat = 'FP1' and item.productcode = product.code\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: item
type: ALL
possible_keys: item_1,item_5,Item_color,complex1,complex2
key: NULL
key_len: NULL
ref: NULL
rows: 3710
Extra: Using where
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: product
type: eq_ref
possible_keys: PRIMARY,product_idx_004
key: PRIMARY
key_len: 752
ref: cir.item.productcode
rows: 1
Extra: Using where
2 rows in set (0.00 sec)
Even in case there is no proper indexes on product table, optimizer should read it all first (746 rows only) and then use complex1 index to find match in item table by consts, as in the first EXPLAIN.
How to repeat:
1. Create tables:
CREATE TABLE `item` (
`code` varchar(300) NOT NULL default '',
`productcode` varchar(300) NOT NULL default '',
`seq` int(10) unsigned default NULL,
`color` varchar(300) NOT NULL,
`dataformat` varchar(10) default NULL,
`noteseq` varchar(20) default NULL,
`customerspecific` int(10) unsigned default NULL,
`privatelabel` int(10) unsigned default NULL,
`cartonpieces` varchar(100) default NULL,
`cartonweight` varchar(100) default NULL,
`cartonvolume` varchar(100) default NULL,
`palletcarton` varchar(100) default NULL,
`palletvolume` varchar(100) default NULL,
`weight` varchar(100) default NULL,
`length` varchar(100) default NULL,
`cartonlength` varchar(100) default NULL,
`salespriceunit` varchar(20) default NULL,
PRIMARY KEY (`code`(250),`productcode`(250)),
KEY `item_1` (`productcode`(250),`code`(250)),
KEY `item_5` (`productcode`(250),`privatelabel`,`color`(250)),
KEY `item_dataformat` (`dataformat`),
KEY `Item_customerspecific` (`customerspecific`),
KEY `Item_color` (`color`(250)),
KEY `complex1` (`productcode`(250),`color`(250),`dataformat`,`privatelabel`),
KEY `complex2` (`productcode`(250),`color`(250),`dataformat`,`customerspecific`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `product` (
`producttypecode` varchar(100) character set utf8 collate utf8_bin NOT NULL,
`code` varchar(300) character set utf8 collate utf8_bin NOT NULL,
`module` varchar(100) character set utf8 collate utf8_bin default NULL,
`maincolor` varchar(100) character set utf8 collate utf8_bin default NULL,
`p1` varchar(100) character set utf8 collate utf8_bin default NULL,
`p2` varchar(100) character set utf8 collate utf8_bin default NULL,
`p3` varchar(100) character set utf8 collate utf8_bin default NULL,
`p4` varchar(100) character set utf8 collate utf8_bin default NULL,
`slots` int(10) unsigned default NULL,
`imperial` int(10) unsigned default NULL,
`width` varchar(100) character set utf8 collate utf8_bin default NULL,
`thickness` varchar(100) character set utf8 collate utf8_bin default NULL,
`height` varchar(100) character set utf8 collate utf8_bin default NULL,
`seq` int(10) unsigned default NULL,
`maxload` varchar(50) character set utf8 collate utf8_bin default NULL,
PRIMARY KEY (`code`(250)),
UNIQUE KEY `product_idx_004` (`code`(250),`producttypecode`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2. Put some data according to the description.
3. Run EXPLAIN:
explain select count(*) from item, product where item.customerspecific = 0 and item.color = product.maincolor and item.dataformat = 'FP1' and item.productcode = product.code\G
Suggested fix:
Use multiple column indexes when they contains all the columns used in query, even with joins.