数据库存储引擎是数据库底层软件组织,数据库管理系统(DBMS)使用数据引擎进行建立、查询、更新和删除数据。不一样的存储引擎提供不一样的存储机制、索引技巧、锁定水平等功能,使用不一样的存储引擎,还能够 得到特定的功能。如今许多不一样的数据库管理系统都支持多种不一样的数据引擎。MySQL的核心就是存储引擎。mysql
不一样的存储引擎都有各自的特色,以适应不一样的需求,以下表所示:算法
功 能sql |
MYISAM数据库 |
Memory缓存 |
InnoDB安全 |
Archive服务器 |
存储限制数据结构 |
256TB并发 |
RAM |
64TB |
None |
支持事物 |
No |
No |
Yes |
No |
支持全文索引 |
Yes |
No |
No |
No |
支持数索引 |
Yes |
Yes |
Yes |
No |
支持哈希索引 |
No |
Yes |
No |
No |
支持数据缓存 |
No |
N/A |
Yes |
No |
支持外键 |
No |
No |
Yes |
No |
若是要提供提交、回滚、崩溃恢复能力的事物安全(ACID兼容)能力,并要求实现并发控制,InnoDB是一个好的选择
若是数据表主要用来插入和查询记录,则MyISAM引擎能提供较高的处理效率
若是只是临时存放数据,数据量不大,而且不须要较高的数据安全性,能够选择将数据保存在内存中的Memory引擎,MySQL中使用该引擎做为临时表,存放查询的中间结果
若是只有INSERT和SELECT操做,能够选择Archive,Archive支持高并发的插入操做,可是自己不是事务安全的。Archive很是适合存储归档数据,如记录日志信息可使用Archive
使用哪种引擎须要灵活选择,一个数据库中多个表可使用不一样引擎以知足各类性能和实际需求,使用合适的存储引擎,将会提升整个数据库的性能
mysql给开发者提供了查询存储引擎的功能,我这里使用的是MySQL5.1,可使用:
命令来查看MySQL使用的引擎,命令的输出为(我用的Navicat Premium):
看到MySQL给用户提供了这么多存储引擎,包括处理事务安全表的引擎和出来了非事物安全表的引擎。
SHOW VARIABLES LIKE 'storage_engine';
在MySQL中,不须要在整个服务器中使用同一种存储引擎,针对具体的要求,能够对每个表使用不一样的存储引擎。Support列的值表示某种引擎是否能使用:YES表示可使用、NO表示不能使用、DEFAULT表示该引擎为当前默认的存储引擎 。下面来看一下其中几种经常使用的引擎。
InnoDB是事务型数据库的首选引擎,支持事务安全表(ACID),支持行锁定和外键,上图也看到
了,InnoDB是默认的MySQL引擎。InnoDB主要特性有:
一、InnoDB给MySQL提供了具备提交、回滚和崩溃恢复能力的事物安全(ACID兼容)存储引擎。InnoDB锁定在行级而且也在SELECT语句中提供一个相似Oracle的非锁定读。这些功能增长了多用户部署和性能。在SQL查询中,能够自由地将InnoDB类型的表和其余MySQL的表类型混合起来,甚至在同一个查询中也能够混合
二、InnoDB是为处理巨大数据量的最大性能设计。它的CPU效率多是任何其余基于磁盘的关系型数据库引擎锁不能匹敌的
三、InnoDB存储引擎彻底与MySQL服务器整合,InnoDB存储引擎为在主内存中缓存数据和索引而维持它本身的缓冲池。InnoDB将它的表和索引在一个逻辑表空间中,表空间能够包含数个文件(或原始磁盘文件)。这与MyISAM表不一样,好比在MyISAM表中每一个表被存放在分离的文件中。InnoDB表能够是任何尺寸,即便在文件尺寸被限制为2GB的操做系统上
四、InnoDB支持外键完整性约束,存储表中的数据时,每张表的存储都按主键顺序存放,若是没有显示在表定义时指定主键,InnoDB会为每一行生成一个6字节的ROWID,并以此做为主键
InnoDB不建立目录,使用InnoDB时,MySQL将在MySQL数据目录下建立一个名为ibdata1的10MB大小的自动扩展数据文件,以及两个名为ib_logfile0和ib_logfile1的5MB大小的日志文件
MyISAM基于ISAM存储引擎,并对其进行扩展。它是在Web、数据仓储和其余应用环境下最常使用的存储引擎之一。MyISAM拥有较高的插入、查询速度,但不支持事物。MyISAM主要特性有:
一、大文件(达到63位文件长度)在支持大文件的文件系统和操做系统上被支持
二、当把删除和更新及插入操做混合使用的时候,动态尺寸的行产生更少碎片。这要经过合并相邻被删除的块,以及若下一个块被删除,就扩展到下一块自动完成
三、每一个MyISAM表最大索引数是64,这能够经过从新编译来改变。每一个索引最大的列数是16
四、最大的键长度是1000字节,这也能够经过编译来改变,对于键长度超过250字节的状况,一个超过1024字节的键将被用上
六、NULL被容许在索引的列中,这个值占每一个键的0~1个字节
八、每一个MyISAM类型的表都有一个AUTO_INCREMENT的内部列,当INSERT和UPDATE操做的时候该列被更新,同时AUTO_INCREMENT列将被刷新。因此说,MyISAM类型表的AUTO_INCREMENT列更新比InnoDB类型的AUTO_INCREMENT更快
使用MyISAM引擎建立数据库,将产生3个文件。文件的名字以表名字开始,扩展名之处文件类型:frm文件存储表定义、数据文件的扩展名为.MYD(MYData)、索引文件的扩展名时.MYI(MYIndex)
MEMORY存储引擎将表中的数据存储到内存中,未查询和引用其余表数据提供快速访问。MEMORY主要特性有:
一、MEMORY表的每一个表能够有多达32个索引,每一个索引16列,以及500字节的最大键长度
六、MEMORY支持AUTO_INCREMENT列和对可包含NULL值的列的索引
七、MEMORY表在所由客户端之间共享(就像其余任何非TEMPORARY表)
八、MEMORY表内存被存储在内存中,内存是MEMORY表和服务器在查询处理时的空闲中,建立的内部表共享
九、当再也不须要MEMORY表的内容时,要释放被MEMORY表使用的内存,应该执行DELETE FROM或TRUNCATE TABLE,或者删除整个表(使用DROP TABLE)
一、Hash存储引擎
表明数据库:redis、memcache等
一般也常见于其余存储引擎的查找速度优化上。 Hash 索引结构的特殊性,其检索效率很是高,索引的检索能够一次定位,不像B-Tree 索引须要从根节点到枝节点,最后才能访问到页节点这样屡次的IO访问,因此 Hash 索引的查询效率要远高于 B-Tree 索引。虽然 Hash 索引效率高,可是 Hash 索引自己因为其特殊性也带来了不少限制和弊端。
这里列举缺点:
(1)Hash 索引仅仅能知足"=","IN"和"<=>"查询,不能使用范围查询。
(2)Hash 索引没法被用来避免数据的排序操做。
(3)Hash 索引不能利用部分索引键查询。
(4)Hash 索引在任什么时候候都不能避免表扫描。
Hash碰撞,就是链式扫描:
因为不一样索引键存在相同 Hash 值,因此即便取知足某个 Hash 键值的数据的记录条数,也没法从 Hash索引中直接完成查询,仍是要经过访问表中的实际数据进行相应的比较,并获得相应的结果。
(5)Hash 索引遇到大量Hash值相等的状况后性能并不必定就会比B-Tree索引高。
二、B树存储引擎
表明数据库:MongoDB、mysql(基本上关系型数据库)等
还有一种算是B树存储引擎:COLA树(CacheObliviousBTree)
表明数据库:tokudb
为了如何让B树更有效的执行,他们提出了一个缓存忘却CacheOblivious算法,该算法在不须要明确知道存储器层次中数据传输规模的状况下,也能够高效的工做。更多请参见:https://en.wikipedia.org/wiki/Cache-oblivious_algorithm。
说个你们熟悉的名称TokuMX : 目前很是流行的NoSQL数据库MongoDB的底层替换成与TokuDB一样的存储引擎[ ToKuMx],达到了很是好的效 果
三、LSM树(Log-Structured Merge Tree)存储引擎
表明数据库:nessDB、leveldb、hbase等
核心思想的核心就是放弃部分读能力,换取写入的最大化能力。LSM Tree ,这个概念就是结构化合并树的意思,它的核心思路其实很是简单,就是假定内存足够大,所以不须要每次有数据更新就必须将数据写入到磁盘中,而能够先将最新的数据驻留在磁盘中,等到积累到最后多以后,再使用归并排序的方式将内存内的数据合并追加到磁盘队尾(由于全部待排序的树都是有序的,能够经过合并排序的方式快速合并到一块儿)。
日志结构的合并树(LSM-tree)是一种基于硬盘的数据结构,与B-tree相比,能显著地减小硬盘磁盘臂的开销,并能在较长的时间提供对文件的高速插入(删除)。然而LSM-tree在某些状况下,特别是在查询须要快速响应时性能不佳。一般LSM-tree适用于索引插入比检索更频繁的应用系统。Bigtable在提供Tablet服务时,使用GFS来存储日志和SSTable,而GFS的设计初衷就是但愿经过添加新数据的方式而不是经过重写旧数据的方式来修改文件。而LSM-tree经过滚动合并和多页块的方法推迟和批量进行索引更新,充分利用内存来存储近期或经常使用数据以下降查找代价,利用硬盘来存储不经常使用数据以减小存储代价。
磁盘的技术特性:对磁盘来讲,可以最大化的发挥磁盘技术特性的使用方式是:一次性的读取或写入固定大小的一块数据,并尽量的减小随机寻道这个操做的次数。
LSM和Btree差别就要在读性能和写性能进行舍和求。在牺牲的同事,寻找其余方案来弥补。
一、LSM具备批量特性,存储延迟。当写读比例很大的时候(写比读多),LSM树相比于B树有更好的性能。由于随着insert操做,为了维护B树结构,节点分裂。读磁盘的随机读写几率会变大,性能会逐渐减弱。 屡次单页随机写,变成一次多页随机写,复用了磁盘寻道时间,极大提高效率。
二、B树的写入过程:对B树的写入过程是一次原位写入的过程,主要分为两个部分,首先是查找到对应的块的位置,而后将新数据写入到刚才查找到的数据块中,而后再查找到块所对应的磁盘物理位置,将数据写入去。固然,在内存比较充足的时候,由于B树的一部分能够被缓存在内存中,因此查找块的过程有必定几率能够在内存内完成,不过为了表述清晰,咱们就假定内存很小,只够存一个B树块大小的数据吧。能够看到,在上面的模式中,须要两次随机寻道(一次查找,一次原位写),才可以完成一次数据的写入,代价仍是很高的。
三、LSM Tree放弃磁盘读性能来换取写的顺序性,彷佛会认为读应该是大部分系统最应该保证的特性,因此用读换写彷佛不是个好买卖。但别急,听我分析一下。
a、内存的速度远超磁盘,1000倍以上。而读取的性能提高,主要仍是依靠内存命中率而非磁盘读的次数
b、写入不占用磁盘的io,读取就能获取更长时间的磁盘io使用权,从而也能够提高读取效率。例如LevelDb的SSTable虽然下降了了读的性能,但若是数据的读取命中率有保障的前提下,由于读取可以得到更多的磁盘io机会,所以读取性能基本没有下降,甚至还会有提高。而写入的性能则会得到较大幅度的提高,基本上是5~10倍左右。
下面说说详细例子:
LSM Tree弄了不少个小的有序结构,好比每m个数据,在内存里排序一次,下面100个数据,再排序一次……这样依次作下去,我就能够得到N/m个有序的小的有序结构。
在查询的时候,由于不知道这个数据究竟是在哪里,因此就从最新的一个小的有序结构里作二分查找,找获得就返回,找不到就继续找下一个小有序结构,一直到找到为止。
很容易能够看出,这样的模式,读取的时间复杂度是(N/m)*log2N 。读取效率是会降低的。
这就是最原本意义上的LSM tree的思路。那么这样作,性能仍是比较慢的,因而须要再作些事情来提高,怎么作才好呢?
LSM Tree优化方式:
a、Bloom filter: 就是个带随即几率的bitmap,能够快速的告诉你,某一个小的有序结构里有没有指定的那个数据的。因而就能够不用二分查找,而只需简单的计算几回就能知道数据是否在某个小集合里啦。效率获得了提高,但付出的是空间代价。
b、compact:小树合并为大树:由于小树他性能有问题,因此要有个进程不断地将小树合并到大树上,这样大部分的老数据查询也能够直接使用log2N的方式找到,不须要再进行(N/m)*log2n的查询了