题目算对本文的一个概括,但我不想一上来就对这两个MySQL引擎一顿比较。这篇博客的切入点,一切的一切都是因为别人问了我一句:MySQL的数据结构是什么?
听到这个问题,脑子里B+树、B树、Hash争着往外蹦,可是没蹦出去,因为忽然想到,这不是索引的数据结构吗?索引的数据结构和数据库的数据结构是一个东西?可是数据库本质上就是文件数据存储当然有数据结构,索引它凭什么有数据结构这么一说?一连串的灵魂拷问让索引忽然变得好抽象,我怎么突然什么都不确定了。
那就捋一捋吧,先纠正自己的两个理解误区:
误区一:B树、B+树包括Hash不是说是索引的数据结构,准确的说是索引的!结构,就是索引结构嘛,贴一张索引的百度词条:
相当于说这个目录长的和B+树一样。
误区二:数据结构的意思就是数据是怎么放的,比如在B树中数据直接放在节点里,而B+树只有叶子节点才有数据。所以索引结构就是数据库的数据结构,有点绕,总之数据库的数据结构就是B树,B+树包括Hash这些。
在梳理这两个理解误区的过程中,巧了还发现自己的两个认知误区。都知道索引可以分好多类,按索引列是否为主键可以分为主键索引和普通索引,按叶子节点是否存有全部数据还是只有数据的一个索引编码可以分为聚簇索引和非聚簇索引,有两个认知误区:
误区一:建索引的时候可以选择建聚簇索引还是非聚簇索引(这个其实是想当然)。
误区二:主键索引就是聚簇索引,普通索引就是非聚簇索引。
反思了一下为什么会有这两个误区,可能是因为现在MySQL默认的引擎是InnoDB,而工作中一般不涉及更换选择其他引擎例如MyISAM,所以满脑子都是InnoDB,什么都是InnoDB,这样下来肯定会有问题。其实MySQL的索引在InnoDB中只有聚簇索引,在MyISAM中只有非聚簇索引,现在想想建索引的时候好像确实没有选择聚簇还是非聚簇。至于主键索引和普通索引,在InnoDB中都会存在,因为InnoDB中必须要有一个主键,哪怕不指定主键也默认生成一个6位的作为主键,所以InnoDB中肯定有主键索引。而同时InnoDB中的索引都是聚簇索引,可能这导致我误解成了前半句,后半句估计是我想当然出来的,InnoDB中也有普通索引,InnoDB中的普通索引也是聚簇索引,只有MyISAM中的普通索引才是非聚簇索引,而且MyISAM中是允许没有主键的。
说了这么多,终于开始提到两种引擎MyISAM和InnoDB了,那就抓住机会扣个题吧。先罗列一下这两种引擎的区别:
1.InnoDB是行级锁,MyISAM是表级锁。
2.InnoDB支持外键,MyISAM不支持。
3.InnoDB支持事务,MyISAM不支持。
4.InnoDB属于索引组织表,MyISAM属于堆表。
5.InnoDB必须有主键,MyISAM不一定。
6.InnoDB索引都是聚簇索引,MyISAM都是非聚簇索引。
7.InnoDB不保存表的总行数,MyISAM保存着。所以count(*)的时候InnoDB要去扫描全表记录行数,MyISAM直接拿快的很。
8.InnoDB不支持FullText全文索引,而MyISAM支持。当然InnoDB可以通过插件实现全文索引。
一下子罗列了这么多,看看就行了,我也记不住。有一个问题可以思考一下,为什么MyISAM适合查询较多的情况而InnoDB适合增删改较多的情况。从以上罗列的8条区别中也可以找到部分答案,因为MyISAM不支持事务,所以增删改过多不合适。但是为什么MyISAM的查询效率会实打实的比InnoDB高的,按理说MyISAM表级锁颗粒度应该更高啊。即使说MyISAM中的索引都是非聚簇索引,叶子节点只有数据编码,必然需要回表,如果InnoDB索引覆盖,聚簇索引叶子节点直接就能取到数据不需要回表,这种情况下哪个快呢?我没有去深究这个问题,去网上搜了一下为什么MyISAM查询效率比InnoDB快,贴一些一致的答案:
1.select的时候InnoDB要缓存所有查询的数据块,而MyISAM只需要缓存索引快。
2.InnoDB寻址要先映射到块,再映射到行,而MyISAM记录的直接就是文件的offset,数据的定位比InnoDB快。
3.InnoDB因为支持事务,还需要维护MVCC一致,即使查询不涉及到事务,但是还是有一个检查和维护MVCC的过程。可以顺便提一下InnoDB是怎么实现MVCC(多版本并发控制)的,其实就是为每一行记录追加两个额外的隐藏值,一个记录这行数据何时被创建,一个记录这行数据何时过期,但是不是真的通过两个时间来记录,而是通过系统版本号的方式表示,所以这个系统版本号越来越大,这么一来每次都要去维护这个系统版本号确实挺耗时间的。
这么看来MyISAM的查询效率确实比InnoDB要快不少,人家甩膀子生活没压力啊。
最后再扣一下题,这么选择这两个引擎呢,想一想前面罗列的8点区别,再考虑一下以下几个问题:
1.数据是否有外键
2.需要支持事务吗
3.需要全文索引吗
4.数据量大不大,大的话就用InnoDB,数据不多就用MyISAM吧,还能全文索引呢。