繁体   English   中英

mysql在MyISAM和InnoDB之间的索引使用差异

[英]mysql difference in index usage between MyISAM and InnoDB

我有这些小桌子, itemcategory

CREATE TABLE `item` (
  `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(150) NOT NULL,
  `category_id` mediumint(8) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  KEY `name` (`name`),
  KEY `category_id` (`category_id`)
) CHARSET=utf8

CREATE TABLE `category` (
  `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(150) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `name` (`name`)
) CHARSET=utf8

我插入了100个类别和1000个项目。

如果我运行这个:

EXPLAIN SELECT item.id,category.name AS category_name FROM item JOIN category ON item.category_id=category.id;

然后,如果表的引擎是InnoDB我得到:

+----+-------------+----------+-------+---------------+-------------+---------+--------------------+------+-------------+
| id | select_type | table    | type  | possible_keys | key         | key_len | ref                | rows | Extra       |
+----+-------------+----------+-------+---------------+-------------+---------+--------------------+------+-------------+
|  1 | SIMPLE      | category | index | PRIMARY       | name        | 452     | NULL               |  103 | Using index |
|  1 | SIMPLE      | item     | ref   | category_id   | category_id | 3       | dbname.category.id |    5 | Using index |
+----+-------------+----------+-------+---------------+-------------+---------+--------------------+------+-------------+

然而,如果我切换到MyISAM(使用alter table engine=myisam ),我得到:

+----+-------------+----------+--------+---------------+---------+---------+-------------------------+------+-------+
| id | select_type | table    | type   | possible_keys | key     | key_len | ref                     | rows | Extra |
+----+-------------+----------+--------+---------------+---------+---------+-------------------------+------+-------+
|  1 | SIMPLE      | item     | ALL    | category_id   | NULL    | NULL    | NULL                    | 1003 |       |
|  1 | SIMPLE      | category | eq_ref | PRIMARY       | PRIMARY | 3       | dbname.item.category_id |    1 |       |
+----+-------------+----------+--------+---------------+---------+---------+-------------------------+------+-------+

我的问题是,为什么处理索引的方式存在差异?

在InnoDB中,任何辅助索引内部都包含表的主键列。 因此列(名称)上的索引名称隐含在列(name,id)上。

这意味着EXPLAIN将您对类别表的访问权限显示为“索引扫描”(这在类型列中显示为“索引”)。 通过扫描索引,它还可以访问id列,它用于查找第二个表item中的行。

然后它还利用了(category_id)上的项索引,它实际上是(category_id,id),只需通过读取索引就可以为select-list获取item.id。 根本不需要读取该表(这在Extra列中显示为“Using index”)。

MyISAM不以这种方式使用辅助密钥存储主键,因此无法获得相同的优化。 对类别表的访问是“ALL”类型,表示表扫描。

我期望对MyISAM表项的访问将是“ref”,因为它使用(category_id)上的索引查找行。 但是如果表中的行数很少,或者自创建索引以来没有完成ANALYZE TABLE item ,优化程序可能会得到偏差的结果。


重新更新:

看起来优化器更喜欢对表扫描进行索引扫描,因此它有机会在InnoDB中进行索引扫描,并将类别表放在第一位。 优化程序决定重新排序表,而不是按照查询中给出的顺序使用表。

在MyISAM表中,将有一个表扫描它首先选择访问哪个表,但是通过将类别表放在第二个,它将连接到类别的PRIMARY键索引而不是item的辅助索引。 优化器更喜欢查找唯一键或主键(键入“eq_ref”)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM