MyISAM与Innodb是MySQL中两个常用的数据库存储引擎。MySQL默认的存储引擎是MyISAM,Innodb是后来推出的一个存储引擎,支持MVCC模式的读写。下面就对两种数据库存储引擎简单介绍。
索引
数据库中的其他索引进行简单分析一下。我们常见到的索引主要有以下几种:
1)唯一索引:用来标识一列或者几列的组合中不准有重复的值;
sql:create index index_type index_name on table_name (col1, col2);
2)聚集索引(Clustering Index)):表数据按照索引的顺序来存储的。对于聚集索引,叶子结点即存储了真实的数据行,不再有另外单独的数据页。mysql中也只有innodb和soliddb引擎支持。现在聚集索引无法指定其他列,现在innodb是按照主键进行聚集索引的。所以如果innodb中没定义主键,它会使用唯一非空索引代替,如果没这种索引则会创建一个隐藏主键;
3)非聚集索引:表数据存储顺序与索引顺序无关。叶结点包含索引字段值及指向数据页数据行主键的逻辑指针,注意是主键值而不是主键所在的行。这样子对主键所在的行数更改之后,则其对应的非聚集索引就可以不用变动了。非聚集索引的行数量与数据表行数据量一致(MyISAM),很容易理解,因为每行对应主键所在行,所以行数肯定是相同的。当查询的时候是针对非聚集索引查询的时候,会出现两次查询,第一次是通过非聚集索引查找出该行对应的主键,然后通过主键得到数据。从此也可以看出指向数据行的主键而不是数据行的地址有好处也有弊端的;
4)主索引(Primary key):主索引是一个有序的文件,这个文件中的记录有两个字段是定长的:第一个字段是数据文件中数据类型相同的字段,并且这个字段作为排序键字段(称为主键);第二个字段是一个到磁盘块(块地址)的指针
5)辅助索引(Secondary key):辅助索引也是有两个字段的有序文件。第一个字段是索引字段,有相同的数据类型,并且是数据文件中的非排序字段,第二个字段可以是一个块指针也可以是记录指针。
另外还有稠密索引,稀疏索引,在这里就不详述。
存储引擎
MySQL两种存储引擎MyISAM与Innod在不同的场景两种存储引擎会有不同的效率。其中MyISAM读的效率是优于Innodb的,这和MyISAM的存储数据的数据结构有关。虽然两个存储引擎使用的都是B+Tree,但是对于MyISAM索引,叶节点存储的是数据的位置。叶节点存储了从跟节点到叶节点之间所有节点数据,而且叶节点之间也是通过指针相互联通。在磁盘上它的数据文件,索引文件也是分开存储的。当进行数据库迁移的时候,可以直接对数据文件拷贝再做一些操作就好了。如下图给出它的索引数据结构:
对于Innodb叶节点存储的是就是数据本身,它不会在当中存储数据的真实位置,叶节点就是数据本身了。除此之外,Innodb所有的文件都会存储在磁盘的一个文件中,包括数据文件,索引文件等。这就会导致Innodb的文件庞大无比,当进行数据重新load的时候会费时费力。下图给出了Innodb的索引数据结构:
读取速度和加载进内存有关系,加载进内存的时候会根据局部性原理与磁盘预读把周围的数据也一起加载。每次加载进内存的数据量是固定的一般都是按照一个内存页大小来加载的。一个内存页一般是4k,而数据库一般一个数据页是16k。在加载的时候需要几个内存页。通过上述两个图可以看出,MyISAM因为它的叶节点存储的数据量更小,每次加载近内存的时候,可以加载进去的索引块更多。加载进去的索引快更多,可以查询的数据就会更多,相对Innodb则在一定程度上查询速度会比较好。
那为何写的效率没有Innodb高那,是因为MyISAM采用的是表锁的锁机制,而Innodb是用行锁的锁机制。所以对于MyISAM存储引擎来说,写或者更新的时候都会锁住整个表格;而Innodb则不会。但是Innodb并不是绝对保证只会行锁,当Innodb不能确定对某一行进行操作的时候也是会锁住整个表。比如:
update tablename set column_name2 = 1 where column_name1 like “XXX”
因为这个时候数据库无法确定对哪一行进行操作,所以还是会锁住整个表格。
加锁分析
读写的加锁分析,请查看文章底部给出的连接。
两种存储引擎之间的差别是非常多的,包括Innodb是没有存储表的行数等细节差别,在这里不再细说。