开发者

MySql query not using composite indices

I have matching Btree indices on 2 tables, but the explain plan says the engine is doing a full scan on one of the tab开发者_如何学Cles and it is very slow. When deployed both will start with ~750,000 rows, the relationship is em_localitems:em_submenuitemassoc => 1:n. My understanding is that the indices below with ** should work well in the query below as they are used left to right.

CREATE TABLE IF NOT EXISTS em_localitems (
  localitemid int(11) NOT NULL AUTO_INCREMENT,
  profitcenterid int(11) DEFAULT NULL,
  productid int(11) DEFAULT NULL,
  PRIMARY KEY (localitemid),
  UNIQUE KEY locationid (profitcenterid,productid),
  **KEY productid_2 (productid,profitcenterid)**
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 ;


CREATE TABLE IF NOT EXISTS em_submenuitemassoc (
  submenuitemassocid int(11) NOT NULL AUTO_INCREMENT,
  productid int(11) NOT NULL,
  profitcenterid int(11) NOT NULL DEFAULT '0',
  submenuid int(11) NOT NULL,
  enddate datetime DEFAULT NULL,
  PRIMARY KEY (submenuitemassocid),
  UNIQUE KEY productid (productid,profitcenterid,submenuid),
  **KEY productid_3 (productid,profitcenterid,submenuid)**
) ENGINE=MyISAM  DEFAULT CHARSET=latin1;

This is the query:

SELECT * from
em_submenuitemassoc sm
LEFT outer JOIN em_localitems li2 on li2.productid=sm.productid
  and li2.profitcenterid=sm.profitcenterid
  and sm.profitcenterid is not null

I also tried index hinting:

SELECT * from
em_submenuitemassoc sm **use index(productid_3)**
LEFT outer JOIN em_localitems li2 on li2.productid=sm.productid
  and li2.profitcenterid=sm.profitcenterid
  and sm.profitcenterid is not null

"show index from em_submenuitemassoc;" returns this:

+---------------------+------------+----------------+--------------+--------------------+-----------+-------------+----------+--------+------+------------+---------+
| Table               | Non_unique | Key_name       | Seq_in_index | Column_name        | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+---------------------+------------+----------------+--------------+--------------------+-----------+-------------+----------+--------+------+------------+---------+
| em_submenuitemassoc |          1 | productid_3    |            1 | productid          | A         |        1136 |     NULL | NULL   |      | BTREE      |         | 
| em_submenuitemassoc |          1 | productid_3    |            2 | profitcenterid     | A         |        1136 |     NULL | NULL   |      | BTREE      |         | 
| em_submenuitemassoc |          1 | productid_3    |            3 | submenuid          | A         |        1136 |     NULL | NULL   |      | BTREE      |         | 
+---------------------+------------+----------------+--------------+--------------------+-----------+-------------+----------+--------+------+------------+---------+

This is the explain plan:

+----+-------------+-------+------+------------------------+-------------+---------+--------------------------------------------------+------+-------+
| id | select_type | table | type | possible_keys          | key         | key_len | ref                                              | rows | Extra |
+----+-------------+-------+------+------------------------+-------------+---------+--------------------------------------------------+------+-------+
|  1 | SIMPLE      | sm    | ALL  | NULL                   | NULL        | NULL    | NULL                                             | 1136 |       | 
|  1 | SIMPLE      | li2   | ref  | locationid,productid_2 | productid_2 | 10      | datatest.sm.profitcenterid,datatest.sm.productid |    1 |       | 
+----+-------------+-------+------+------------------------+-------------+---------+--------------------------------------------------+------+-------+

What's so horribly wrong with this?


See that your query acces type for table sm is "ALL". The optimizer knows it has to read all the rows of sm regardless of the join conditions.

This is probably because you're using LEFT OUTER JOIN which returns all the rows of the left table in the join, regardless of whether there are matching rows in the right table of the join.

You're also using SELECT * so it'll have to fetch all the columns of sm anyway. If the query required only the columns in the index, it would be able to skip reading the base table.

So there's no benefit in this query to using the index, and MySQL gains more efficiency by skipping reading the index.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜