【MySQl】MyISAM和InnoDB索引对比

部分内容转自:http://www.2cto.com/database/201211/172380.html

比较好的文章:http://www.cnblogs.com/hustcat/archive/2009/10/28/1591648.html

MyISAM

MyISAM引擎使用B+Tree作为索引结构,叶节点的data域存放的是数据记录的地址。下图是MyISAM索引的原理图:

这里设表一共有三列,假设我们以Col1为主键,则上图是一个MyISAM表的主索引(Primary key)示意。可以看出MyISAM的索引文件仅仅保存数据记录的地址。在MyISAM中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的key可以重复。如果我们在Col2上建立一个辅助索引,则此索引的结构如下图所示:

同样也是一颗B+Tree,data域保存数据记录的地址。因此,MyISAM中索引检索的算法为首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,则取出其data域的值,然后以data域的值为地址,读取相应数据记录。
MyISAM的索引方式也叫做“非聚集”的,之所以这么称呼是为了与InnoDB的聚集索引区分。

InnoDB
虽然InnoDB也使用B+Tree作为索引结构,但具体实现方式却与MyISAM截然不同。
第一个重大区别是InnoDB的数据文件本身就是索引文件。从上文知道,MyISAM索引文件和数据文件是分离的,索引文件仅保存数据记录的地址。而在InnoDB中,表数据文件本身就是按B+Tree组织的一个索引结构,这棵树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引。
上图是InnoDB主索引(同时也是数据文件)的示意图,可以看到叶节点包含了完整的数据记录。这种索引叫做聚集索引。因为InnoDB的数据文件本身要按主键聚集,所以InnoDB要求表必须有主键(MyISAM可以没有),如果没有显式指定,则MySQL系统会自动选择一个可以唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL自动为InnoDB表生成一个隐含字段作为主键,这个字段长度为6个字节,类型为长整形。
第二个与MyISAM索引的不同是InnoDB的辅助索引data域存储相应记录主键的值而不是地址。换句话说,InnoDB的所有辅助索引都引用主键作为data域。例如,下图为定义在Col3上的一个辅助索引:
这里以英文字符的ASCII码作为比较准则。聚集索引这种实现方式使得按主键的搜索十分高效,但是辅助索引搜索需要检索两遍索引:首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录。
了解不同存储引擎的索引实现方式对于正确使用和优化索引都非常有帮助,例如知道了InnoDB的索引实现后,就很容易明白为什么不建议使用过长的字段作为主键,因为所有辅助索引都引用主索引,过长的主索引会令辅助索引变得过大。再例如,用非单调的字段作为主键在InnoDB中不是个好主意因为InnoDB数据文件本身是一颗B+Tree,非单调的主键会造成在插入新记录时数据文件为了维持B+Tree的特性而频繁的分裂调整,十分低效,而使用自增字段作为主键则是一个很好的选择。
联合索引或者叫做复合索引、组合索引,在《MySQL技术内幕InnoDB存储引擎》的‘5.6.4联合索引’章节有一些描述(第二版内容无更新),是指对表上的多个列做索引,联合索引也是一颗B+树,联合索引的键值的数量不是1,而是大于等于2,show index如下:
mysql> show create table t2;
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                                                                                                    |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t2    | CREATE TABLE `t2` (`column_a` int(11) DEFAULT NULL,`column_b` int(11) DEFAULT NULL,`column_c` int(11) DEFAULT NULL,`column_d` varchar(10) DEFAULT NULL,KEY `index_a_b_c` (`column_a`,`column_b`,`column_c`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)mysql> show index  from t2 \G
*************************** 1. row ***************************Table: t2Non_unique: 1Key_name: index_a_b_cSeq_in_index: 1Column_name: column_aCollation: ACardinality: 9Sub_part: NULLPacked: NULLNull: YESIndex_type: BTREEComment:
Index_comment:
*************************** 2. row ***************************Table: t2Non_unique: 1Key_name: index_a_b_cSeq_in_index: 2Column_name: column_bCollation: ACardinality: 9Sub_part: NULLPacked: NULLNull: YESIndex_type: BTREEComment:
Index_comment:
*************************** 3. row ***************************Table: t2Non_unique: 1Key_name: index_a_b_cSeq_in_index: 3Column_name: column_cCollation: ACardinality: 9Sub_part: NULLPacked: NULLNull: YESIndex_type: BTREEComment:
Index_comment:
3 rows in set (0.00 sec)mysql> select count(*) from t2;
+----------+
| count(*) |
+----------+
|        9 |
+----------+
1 row in set (0.01 sec)

show index语法的说明:

1、Table:索引所在的表名。
2、Non_unique:非唯一的索引,可以看到primary key是0,因为必须是唯一的。
3、Key_name:索引的名称,我们可以通过这个名称来drop index。
4、Seq_in_index:索引中该列的位置,如果看联合索引就比较直观。(例如上面例子)
5、Column_name:索引的列。
6、Collation:列以什么方式存储在索引中。可以是‘A’或者NULL。B+树索引总是A,即排序的。如果使用了Heap存储索引,并且建立了Hash索引,这里就会显示NULL。因为Hash根据Hash桶来存放索引数据,而不是对数据进行排序。
7、Cardinality:非常关键的值,表示索引中唯一值得数目的估计值,优化器会根据这个值来判断查询是否使用这个索引。Cardinality/表的行数的比值应尽可能接近1,如果非常小,那么需要考虑是否还需要建这个索引。这个值不是实时更新的,因为开销会很大,可以通过运行ANALYZE TABLE或myisamchk -a可以更新这个值。
8、Sub_part:是否是列的部分被索引。假设如果看index_a这个索引,这里显示10,表示只索引a列的前10个字符。如果索引整个列,则该字段为NULL。
9、Packed:关键字如何被压缩。如果没有被压缩,则为NULL。
10、Null:是否索引的列含有NULL值。可以看到index_a_b_c这里为YES,因为我们定义的a、b、c列允许NULL值。
11、Index_type:索引的类型。InnoDB存储引擎只支持B+树索引,所以这里显示的都是BTREE。
12、Comment:注释。

联合索引形象的说明可以比喻成手机中的电话薄,因为联合索引是多个键值的B+树情况,和单列索引的键值顺序排序相同,使用联合索引也是通过叶节点逻辑上的顺序地读出所有数据,比如表中column1和column2要建一个index_1_2,那这个联合索引会先按照column1顺序存放,在column1值相同的数据,再使用coiumn2顺序存放。例如:(1,1),(1,2),(2,1),(2,4),(3,1),(3,2),按照(column1,column2)的顺序进行存放:

联合索引也可以认为是多列组成的辅助索引,同样引用主键作为data域。
另外联合索引的使用同样需要掌握好规律,如最开始的index_a_b_c这个组合索引,真正能够使用到索引的是:
mysql> explain select * from t2 where column_a=1 and column_b=2 and column_c=3;
+----+-------------+-------+------+---------------+-------------+---------+-------------------+------+-------------+
| id | select_type | table | type | possible_keys | key         | key_len | ref               | rows | Extra       |
+----+-------------+-------+------+---------------+-------------+---------+-------------------+------+-------------+
|  1 | SIMPLE      | t2    | ref  | index_a_b_c   | index_a_b_c | 15      | const,const,const |    1 | Using where |
+----+-------------+-------+------+---------------+-------------+---------+-------------------+------+-------------+
1 row in set (0.00 sec)mysql> explain select * from t2 where column_a=1 and column_b=2;
+----+-------------+-------+------+---------------+-------------+---------+-------------+------+-------------+
| id | select_type | table | type | possible_keys | key         | key_len | ref         | rows | Extra       |
+----+-------------+-------+------+---------------+-------------+---------+-------------+------+-------------+
|  1 | SIMPLE      | t2    | ref  | index_a_b_c   | index_a_b_c | 10      | const,const |    1 | Using where |
+----+-------------+-------+------+---------------+-------------+---------+-------------+------+-------------+
1 row in set (0.00 sec)mysql> explain select * from t2 where column_a=1;
+----+-------------+-------+------+---------------+-------------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key         | key_len | ref   | rows | Extra       |
+----+-------------+-------+------+---------------+-------------+---------+-------+------+-------------+
|  1 | SIMPLE      | t2    | ref  | index_a_b_c   | index_a_b_c | 5       | const |    1 | Using where |
+----+-------------+-------+------+---------------+-------------+---------+-------+------+-------------+
1 row in set (0.00 sec)

另外针对column_a和column_c两列的查询,实际上只是用到了组合索引中的column_a部分:

mysql> explain select * from t2 where column_a=1 and column_c=3;
+----+-------------+-------+------+---------------+-------------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key         | key_len | ref   | rows | Extra       |
+----+-------------+-------+------+---------------+-------------+---------+-------+------+-------------+
|  1 | SIMPLE      | t2    | ref  | index_a_b_c   | index_a_b_c | 5       | const |    2 | Using where |
+----+-------------+-------+------+---------------+-------------+---------+-------+------+-------------+
1 row in set (0.00 sec)

可以看到key_len是5,查询通过索引index_a_b_c的column_a中找到相应column_a=1行的叶子节点逻辑位置区域,但是由于条件column_c无法被使用到索引,遍历了column_a=1的所有行。

所以大家习惯说的联合索引的"最左前缀"的原则,简单的理解就是只从联合索引组合的最左侧的列开始的组合顺序组合。

理解了联合索引机制,什么用不到就更好理解:

mysql> explain select * from t2 where column_b=2 and column_c=3;
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | t2    | ALL  | NULL          | NULL | NULL    | NULL |    9 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)mysql> explain select * from t2 where column_b=2;
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | t2    | ALL  | NULL          | NULL | NULL    | NULL |    9 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)mysql> explain select * from t2 where column_c=3;
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | t2    | ALL  | NULL          | NULL | NULL    | NULL |    9 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

posted on 2014-01-14 12:08 poorX 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/jiangxu67/p/3518752.html

【MySQl】MyISAM和InnoDB索引对比相关推荐

  1. mysql myisam表加索引_MyISAM和InnoDB的索引实现

    在 MySQL 中,主要有四种类型的索引,分别为: B-Tree 索引, Hash 索引, Fulltext 索引和 R-Tree 索引.我们主要分析B-Tree 索引. B-Tree 索引是 MyS ...

  2. mysql myisam和innodb区别_MySQL 万字精华总结 + 面试100 问,吊打面试官绰绰有余

    一.MySQL架构 和其它数据库相比,MySQL有点与众不同,它的架构可以在多种不同场景中应用并发挥良好作用.主要体现在存储引擎的架构上,插件式的存储引擎架构将查询处理和其它的系统任务以及数据的存储提 ...

  3. mysql分页tmp_count,MySQL MyISAM和InnoDB引擎的写入速度优化比较,分页速度优化

    以下的文章主要介绍的是MySQL MyISAM的引擎和InnoDB引擎的实际性能的比较,我们首先是通过MySQL数据库的表结构来出MySQL MyISAM的引擎和InnoDB引擎的实际性能的实际操作. ...

  4. mysql myisam表加索引_MySQL中myisam和innodb的主键索引有什么区别

    ALTER TABLE t1 ADD INDEX(or CREATE INDEX) ALTER TABLE t1 ADD FULLTEXT INDEX ALTER TABLE t1 ADD COLUM ...

  5. MySQL MyISAM和InnoDB存储引擎的比较

    MyISAM是MySQL的默认存储引擎,基于传统的ISAM类型,支持全文搜索,但不是事务安全的,而且不支持外键.每张MyISAM表存放在三个文件中:frm 文件存放表格定义:数据文件是MYD (MYD ...

  6. mysql myisam innodb 区别

    最近连续接到了两次tencent的电话面试,当然不是同一个部门.都涉及到了一个mysql的基础知识问题.为了防止第三次打电话来,备注下.^^. 题目1:讲讲你对mysql myisam,innodb的 ...

  7. mysql--innodb索引原理详解_MYSQL索引机制(InnoDB索引原理详解)

    索引定义和一些概念: 索引(Index)是帮助MySQL高效获取数据的数据结构. 我们知道,数据库查询是数据库的最主要功能之一.但每种查找算法都只能应用于特定的数据结构之上,例如二分查找要求被检索数据 ...

  8. MySQL数据库中的MyISAM和InnoDB存储引擎对比

    一.InnoDB和MylSAM存储引擎对比 MyISAM是MySQL的默认数据库引擎(5.5版之前),由早期的ISAM(Indexed Sequential Access Method:有索引的顺序访 ...

  9. MySQL 两种存储引擎:MyISAM与InnoDB对比及理解

    MySQL 两种存储引擎:MyISAM与InnoDB对比及理解 目前MySQL默认的存储引擎是InnoDB 现在大多数时候我们使用的都是InnoDB存储引擎,但是在某些情况下使用MyISAM更好,比如 ...

最新文章

  1. iOS开发 QQ粘性动画效果
  2. PHP与Java使用des加密通讯
  3. 【数据分析】理解数据分析
  4. java 保护类型_Java 类的受保护访问(学习 Java 编程语言 046)
  5. shell批量创建随机文件名格式文件
  6. 理解 redis 中的 集合对象类型
  7. React Native之react-native bundle --platform android --dev false --entry-file index.js --bundle失败
  8. 点云数据生成三维模型_可直接编辑的高质量3D生成模型:三维深度生成方法SDM-NET...
  9. 前端开发推荐-创建一个精美的jquery图片库效果
  10. linux ll命令时间,linux ll显示时间格式
  11. js操作动态表格内元素
  12. 返回结果乱码_峰哥说技术系列-7 Spring Boot返回JSON
  13. ubunut16.04 更新python3.6
  14. 万能五笔输入法弹窗_万能五笔输入法广告如何彻底关闭
  15. onvif开发踩坑【二】鉴权失败
  16. 相机等效焦距和视场角计算
  17. 风之大陆 服务器不稳定,《风之大陆》手游官网——异世界奇幻冒险MMO手游
  18. 5.16 图层合并的几种方式 [原创Ps教程]
  19. 电脑硬盘分区太多?如何合并分区?
  20. CAN接受和发送失败的原因有哪些---之前调试MCP2515驱动时,数据一直发不出去,三个发送邮箱都被占满.至今未解决,读寄存器-总线错误

热门文章

  1. 《糖豆人:终极淘汰赛》成功背后蕴含了何种设计?
  2. 服务端构架干货:快节奏多人游戏的技术实现
  3. Python基础——PyCharm版本——第四章、基础语法-分支语句(条件判断if语句)
  4. No module named pip
  5. 现在给你三百台服务器,你怎么对他们进行管理?
  6. python 中 pynlpir错误 Cannot Open Configure file pynlpir解决
  7. MySQL 5.1同步到5.5卡库问题一则
  8. oracle11g自动内存管理
  9. ldap集成nginx
  10. Go goroutine