当前市面上能见到的数据库有340多种, 每一种数据库会有一个或者多个数据引擎, 通过对这些存储引擎的分类, 能够帮助我们了解一些共性的东西。
为什么我们需要不同类型的存储引擎? 因为我们希望能够读写的性能能够最优, 不同的操作引擎, 对于一个写操作或者读操作, 需要的操作是不同的; 相同的操作应用于不同的介质速度也是不同的。 如下是从网上的得到Jeff Dean 的不同介质的访问时间:
操作类型 | 需要时间 |
---|---|
L1 cache reference 读取CPU的一级缓存 | 0.5 ns |
Branch mispredict(转移、分支预测) | 5 ns |
L2 cache reference 读取CPU的二级缓存 | 7 ns |
Mutex lock/unlock 互斥锁\解锁 | 100 ns |
Main memory reference 读取内存数据 | 100 ns |
Compress 1K bytes with Zippy 1k字节压缩 | 10 us |
Send 2K bytes over 1 Gbps network 在1Gbps的网络上发送2k字节 | 20 us |
Read 1 MB sequentially from memory 从内存顺序读取1MB | 250 us |
Round trip within same datacenter 从一个数据中心往返一次,ping一下 | 500 us |
Disk seek 磁盘搜索 | 10 ms |
Read 1 MB sequentially from network 从网络上顺序读取1兆的数据 | 10 ms |
Read 1 MB sequentially from disk 从磁盘里面读出1MB | 30 ms |
Send packet CA->Netherlands->CA 一个包的一次远程访问 | 150 ms |
根据索引的数据结构分类
不同的数据结构, 有不同的读写特性, 针对不同的场景, 比如, B-tree的读写性能比较平均, LSM结构适合写多读少的场景, Hash的读写比较平均, 但是通常不适合大数据量, 等等。
B-tree
m阶B-Tree满足以下条件:
- 每个节点最多拥有m个子树;
- 根节点至少有2个子树;
- 分支节点至少拥有m/2颗子树(除根节点和叶子节点外都是分支节点);
- 所有叶子节点都在同一层、每个节点最多可以有m-1个key,并且以升序排列;
B+tree
B+树是B树的一个升级版,相对于B树来说B+树更充分的利用了节点的空间,让查询速度更加稳定,其速度完全接近于二分法查找。为什么说B+树查找的效率要比B树更高、更稳定;我们先看看两者的区别
- B+树的非叶子节点不保存关键字记录的指针,这样使得B+树每个节点所能保存的关键字大大增加;
- B+树叶子节点保存了父节点的所有关键字和关键字记录的指针,每个叶子节点的关键字从小到大链接;
- B+树的根节点关键字数量和其子节点个数相等;
- B+的非叶子节点只进行数据索引,不会存实际的关键字记录的指针,所有数据地址必须要到叶子节点才能获取到,所以每次数据查询的次数都一样;
LSM(Log-structured-Merge)tree
LSM tree存储实现思路是将随机写转化为顺序写,尽量保持日志型数据库的写性能优势,并提供相对较好的读性能。具体实现方式如下:
- 当有写操作(或update操作)时,写入位于内存的buffer,内存中通过某种数据结构(如skiplist)保持key有序;
- 一般的实现也会将数据追加写到磁盘Log文件,以备必要时恢复;
- 内存中的数据定时或按固定大小地刷到磁盘,更新操作只不断地写到内存,并不更新磁盘上已有文件;
- 随着越来越多写操作,磁盘上积累的文件也越来越多,这些文件不可写且有序;
- 定时对文件进行合并操作(compaction),消除冗余数据,减少文件数量;
关于LSM非常好的介绍资料:
https://www.zhihu.com/question/19887265
哈希索引
哈希索引(Hash)是另外一种比较简单高效的存储引擎数据结构, 通常运用在NoSQL里面, 并且在数据量不大的情况下, 因为它在内存里面构建K-V或者K-list(V)类型的结构。它的查询效率非常高, 甚至可以只查询一次, 而像B-tree、B+tree一般需要多次, 和树的深度有关, LSM也和level的层数有关。它的特点:
- 查询或者修改的效率高;
- 适合随机查询, 不适合范围查询;
- 不适合存储大数据量;
- hash函数的设计够好, 才能使得分布均匀;
不同索引算法的常见数据库类型:
索引算法 | 数据库 |
---|---|
B-tree | MongoDB |
b+tree | MySQL |
LSM tree | LevelDB、hbase、Cassandra |
Hash | redis |
有上面的介绍可见, 不同的数据结构有不同的特性, 而不同的数据库采用哪一种数据结构, 也是由其支持的应用场景决定的。