《现代 Key-Value 数据库原理:从 B+Tree 到 LSM Tree》-第五篇:现代数据库横向对比

文章目录

  • [《现代 Key-Value 数据库原理:从 B+Tree 到 LSM Tree》](#《现代 Key-Value 数据库原理:从 B+Tree 到 LSM Tree》)
  • 第五篇:现代数据库横向对比
  • [第一章 现代数据库整体分类](#第一章 现代数据库整体分类)
  • [第二章 现代数据库横向总表](#第二章 现代数据库横向总表)
  • [第三章 LMDB](#第三章 LMDB)
  • [3.1 LMDB的数据结构](#3.1 LMDB的数据结构)
  • [3.2 LMDB为什么读取快?](#3.2 LMDB为什么读取快?)
  • [3.3 LMDB的核心优势](#3.3 LMDB的核心优势)
  • [3.4 LMDB的限制](#3.4 LMDB的限制)
  • [第四章 LevelDB](#第四章 LevelDB)
  • [4.1 LevelDB为什么选择LSM?](#4.1 LevelDB为什么选择LSM?)
  • [4.2 LevelDB核心组件](#4.2 LevelDB核心组件)
  • [4.3 LevelDB的缺点](#4.3 LevelDB的缺点)
  • [第五章 RocksDB](#第五章 RocksDB)
  • [5.1 为什么需要RocksDB?](#5.1 为什么需要RocksDB?)
  • [5.2 Column Family](#5.2 Column Family)
  • [5.3 RocksDB适合什么?](#5.3 RocksDB适合什么?)
  • [第六章 BadgerDB](#第六章 BadgerDB)
  • [6.1 为什么Key和Value分开?](#6.1 为什么Key和Value分开?)
  • [6.2 Badger适合什么?](#6.2 Badger适合什么?)
  • [第七章 BoltDB / bbolt](#第七章 BoltDB / bbolt)
  • [7.1 bbolt结构](#7.1 bbolt结构)
  • [7.2 bbolt与LMDB](#7.2 bbolt与LMDB)
  • [第八章 SQLite](#第八章 SQLite)
  • [8.1 SQLite底层是什么?](#8.1 SQLite底层是什么?)
  • [8.2 SQLite最大的特点](#8.2 SQLite最大的特点)
  • [8.3 SQLite为什么这么流行?](#8.3 SQLite为什么这么流行?)
  • [8.4 SQLite vs LMDB](#8.4 SQLite vs LMDB)
  • [第九章 Berkeley DB](#第九章 Berkeley DB)
  • [9.1 Berkeley DB适合什么?](#9.1 Berkeley DB适合什么?)
  • [第十章 Redis](#第十章 Redis)
  • [10.1 Redis不是单一数据结构](#10.1 Redis不是单一数据结构)
  • [10.2 Redis为什么快?](#10.2 Redis为什么快?)
  • [10.3 Redis为什么还能持久化?](#10.3 Redis为什么还能持久化?)
  • [第十一章 WiredTiger](#第十一章 WiredTiger)
  • [11.1 WiredTiger为什么重要?](#11.1 WiredTiger为什么重要?)
  • [11.2 MongoDB为什么需要独立存储引擎?](#11.2 MongoDB为什么需要独立存储引擎?)
  • [第十二章 Pebble](#第十二章 Pebble)
  • [12.1 Pebble为什么出现?](#12.1 Pebble为什么出现?)
  • [第十三章 TiKV](#第十三章 TiKV)
  • [13.1 TiKV整体架构](#13.1 TiKV整体架构)
  • [13.2 为什么TiKV使用RocksDB思想?](#13.2 为什么TiKV使用RocksDB思想?)
  • [第十四章 FoundationDB](#第十四章 FoundationDB)
  • [14.1 FoundationDB最大的特点](#14.1 FoundationDB最大的特点)
  • [第十五章 B+Tree vs LSM Tree](#第十五章 B+Tree vs LSM Tree)
  • [第十六章 写入性能](#第十六章 写入性能)
  • [第十七章 读取性能](#第十七章 读取性能)
  • [第十八章 Read Amplification](#第十八章 Read Amplification)
  • [第十九章 Write Amplification](#第十九章 Write Amplification)
  • [第二十章 Space Amplification](#第二十章 Space Amplification)
  • [第二十一章 三种放大之间的关系](#第二十一章 三种放大之间的关系)
  • [第二十二章 mmap vs Buffer Pool](#第二十二章 mmap vs Buffer Pool)
    • mmap
    • [Buffer Pool](#Buffer Pool)
  • [22.1 两者区别](#22.1 两者区别)
  • [第二十三章 SSD时代的数据库](#第二十三章 SSD时代的数据库)
  • [23.1 SSD改变的是成本,而不是原理](#23.1 SSD改变的是成本,而不是原理)
  • [第二十四章 HDD、SSD、NVMe对比](#第二十四章 HDD、SSD、NVMe对比)
  • [24.1 HDD](#24.1 HDD)
  • [24.2 NVMe](#24.2 NVMe)
  • [第二十五章 AI数据集应该选什么?](#第二十五章 AI数据集应该选什么?)
  • [第二十六章 日志系统应该选什么?](#第二十六章 日志系统应该选什么?)
  • [第二十七章 缓存系统应该选什么?](#第二十七章 缓存系统应该选什么?)
  • [第二十八章 嵌入式设备应该选什么?](#第二十八章 嵌入式设备应该选什么?)
  • [第二十九章 Go项目应该选什么?](#第二十九章 Go项目应该选什么?)
  • [第三十章 分布式数据库应该选什么?](#第三十章 分布式数据库应该选什么?)
  • [第三十一章 Storage Engine与Database的区别](#第三十一章 Storage Engine与Database的区别)
  • [第三十二章 数据库的分层](#第三十二章 数据库的分层)
  • [第三十三章 为什么没有"最好的数据库"](#第三十三章 为什么没有“最好的数据库”)
  • [第三十四章 从访问模式选择数据库](#第三十四章 从访问模式选择数据库)
  • [第三十五章 AI/视觉行业数据库选择](#第三十五章 AI/视觉行业数据库选择)
  • [第三十六章 一个工业视觉系统应该如何组合?](#第三十六章 一个工业视觉系统应该如何组合?)
  • [第三十七章 B+Tree与LSM Tree的最终理解](#第三十七章 B+Tree与LSM Tree的最终理解)
    • B+Tree
    • [LSM Tree](#LSM Tree)
  • [第三十八章 从LMDB到LevelDB,再到RocksDB](#第三十八章 从LMDB到LevelDB,再到RocksDB)
  • [第三十九章 现代数据库真正的核心技术](#第三十九章 现代数据库真正的核心技术)
  • [第四十章 数据库学习路线](#第四十章 数据库学习路线)
  • [第四十一章 如果要阅读源码,应该先看什么?](#第四十一章 如果要阅读源码,应该先看什么?)
  • [第四十二章 最终总结](#第四十二章 最终总结)

《现代 Key-Value 数据库原理:从 B+Tree 到 LSM Tree》

第五篇:现代数据库横向对比

前面四篇分别从数据库存储基础、B+Tree、LMDB、LevelDB出发,逐渐建立了一个完整的认知体系。

现在可以把这些知识放在一起。

现代数据库看起来种类非常多:

text 复制代码
LMDB
LevelDB
RocksDB
SQLite
Redis
BadgerDB
bbolt
WiredTiger
TiKV
FoundationDB
Pebble

但如果从底层存储结构来看,它们并没有想象中那么复杂。

大量数据库最终都可以归结到几种核心思想:

text 复制代码
B+Tree
LSM Tree
Hash
SkipList
Log Structured Storage
Memory Data Structure
Distributed KV

因此,学习数据库真正重要的不是记住几十个数据库的名字,而是理解:

为什么这个数据库选择这种数据结构,以及这种选择解决了什么问题。


第一章 现代数据库整体分类

先建立一个全局视图。

text 复制代码
                         Database
                            |
          +-----------------+------------------+
          |                 |                  |
          v                 v                  v
       B+Tree             LSM Tree          Memory
          |                 |                  |
     +----+----+       +----+----+        +----+----+
     |         |       |         |        |         |
    LMDB    SQLite  LevelDB   RocksDB   Redis    ...
     |         |       |         |
 bbolt     WiredTiger |     Pebble
                      |
                    TiKV

再进一步:

text 复制代码
B+Tree
   |
   +-- LMDB
   +-- SQLite
   +-- bbolt
   +-- WiredTiger

LSM
   |
   +-- LevelDB
   +-- RocksDB
   +-- Pebble
   +-- BadgerDB
   +-- TiKV

Memory
   |
   +-- Redis

但是需要注意:

现实数据库往往不是纯粹的一种结构。

例如:

text 复制代码
BadgerDB
=
LSM Tree
+
Value Log

Redis:

text 复制代码
Hash
SkipList
Rax
List
Set
Sorted Set

FoundationDB则更加复杂:

text 复制代码
Distributed Transaction

+

Storage Engine

所以:

"数据库属于什么类型"通常应该理解为它的核心存储架构,而不是说整个数据库只包含一种数据结构。


第二章 现代数据库横向总表

先给出本篇最重要的一张表。

数据库 核心结构 核心特点 典型场景
LMDB B+Tree mmap、Copy-On-Write、MVCC、读性能优秀 AI数据集、嵌入式
LevelDB LSM Tree MemTable、SSTable、Compaction 嵌入式KV、日志
RocksDB LSM Tree 高性能、丰富Compaction和缓存优化 高写入、高并发
BadgerDB LSM + Value Log Go生态、Key/Value分离 Go服务
WiredTiger B+Tree等 高性能通用存储引擎 MongoDB
SQLite B+Tree 单文件、完整SQL 桌面、移动、嵌入式
Berkeley DB B+Tree / Hash等 经典嵌入式数据库 嵌入式系统
bbolt B+Tree Go、单文件、简单 Go嵌入式应用
Redis 内存数据结构 极低延迟、丰富数据结构 缓存、消息、实时数据
TiKV RocksDB等LSM 分布式KV、Raft 云原生数据库
Pebble LSM Tree CockroachDB生态 分布式数据库
FoundationDB 分布式KV 强事务、可组合 分布式数据库

第三章 LMDB

LMDB:

text 复制代码
Lightning Memory-Mapped Database

它是OpenLDAP项目中的核心嵌入式数据库之一。

核心设计:

text 复制代码
B+Tree
   +
mmap
   +
Copy-On-Write
   +
MVCC

3.1 LMDB的数据结构

可以简单表示:

text 复制代码
              Root
                |
          +-----+-----+
          |           |
       Branch       Branch
          |           |
       +--+--+     +--+--+
       |     |     |     |
      Leaf  Leaf  Leaf  Leaf

数据库文件:

text 复制代码
data.mdb

直接通过:

text 复制代码
mmap()

映射到进程地址空间。

于是:

text 复制代码
Disk
 |
 v
Virtual Memory
 |
 v
Page
 |
 v
CPU

3.2 LMDB为什么读取快?

传统数据库:

text 复制代码
Disk
 ↓
Read
 ↓
Buffer Pool
 ↓
Copy
 ↓
Application

LMDB:

text 复制代码
Disk
 ↓
mmap
 ↓
Virtual Address
 ↓
Application

因此:

减少了大量:

text 复制代码
系统调用
用户态/内核态切换
数据复制

3.3 LMDB的核心优势

读取优秀

尤其适合:

text 复制代码
大量读取
少量写入

事务简单

采用:

text 复制代码
MVCC

多个Reader可以并发。


数据结构稳定

B+Tree:

text 复制代码
查询:

O(logN)

非常适合AI数据集

例如:

text 复制代码
image_001 → JPEG
image_002 → JPEG
image_003 → JPEG

最终:

text 复制代码
dataset.mdb

3.4 LMDB的限制

最大的特点其实也是最大的限制:

text 复制代码
一个Writer

因此如果业务是:

text 复制代码
大量并发写入

LMDB通常不是第一选择。


第四章 LevelDB

LevelDB 是Google设计的嵌入式KV数据库。

核心:

text 复制代码
LSM Tree

完整写路径:

text 复制代码
Put
 |
 +----> WAL
 |
 +----> MemTable
          |
          v
     Immutable
          |
          v
       SSTable
          |
          v
     Compaction

4.1 LevelDB为什么选择LSM?

因为它希望解决:

text 复制代码
B+Tree

大量随机写

的问题。

LSM:

text 复制代码
Random Write

↓

Memory

↓

Sequential Write

所以:

text 复制代码
写入吞吐

通常非常优秀。


4.2 LevelDB核心组件

text 复制代码
MemTable
SkipList
WAL
Immutable MemTable
SSTable
Bloom Filter
Compaction
Manifest
Snapshot
Iterator

这些概念实际上已经成为现代LSM数据库的基础。


4.3 LevelDB的缺点

LSM不是没有代价。

主要问题:

text 复制代码
Compaction

会导致:

text 复制代码
Write Amplification
Read Amplification
Space Amplification

例如:

text 复制代码
写1GB

↓

后台Compaction

↓

可能产生多个GB的数据读写

所以:

LSM把随机写问题转化成了后台整理问题。


第五章 RocksDB

RocksDB 是基于LevelDB思想发展起来的高性能LSM存储引擎。

可以理解成:

text 复制代码
LevelDB
   |
   +----------------+
   |                |
性能优化         功能扩展
   |                |
   +-------+--------+
           |
        RocksDB

5.1 为什么需要RocksDB?

Facebook面对:

text 复制代码
SSD
NVMe
多核CPU
高并发
海量数据

LevelDB的设计比较简单。

RocksDB进一步强化:

text 复制代码
Compaction
Cache
Concurrency
SSD
Write Buffer
Compression
Column Family
Bloom Filter

5.2 Column Family

RocksDB一个非常重要的设计:

text 复制代码
Column Family

例如:

text 复制代码
Database

├── metadata
├── image
├── feature
└── result

不同数据可以:

text 复制代码
独立配置
独立Compaction
独立Cache策略

这对于大型系统很重要。


5.3 RocksDB适合什么?

例如:

text 复制代码
高写入日志

时序数据

缓存

状态存储

分布式数据库底层存储

如果系统:

text 复制代码
写入量非常大

RocksDB通常比LMDB更值得考虑。


第六章 BadgerDB

BadgerDB 是Go生态中的高性能KV数据库。

核心思想:

text 复制代码
LSM Tree
    +
Value Log

6.1 为什么Key和Value分开?

传统:

text 复制代码
SSTable

Key + Value
Key + Value
Key + Value

如果Value非常大:

text 复制代码
10KB
100KB
1MB

Compaction就会产生大量数据移动。


Badger:

text 复制代码
LSM

Key
Key
Key
Key

而Value:

text 复制代码
Value Log

Value
Value
Value

形成:

text 复制代码
Key

↓

Value Pointer

↓

Value Log

例如:

text 复制代码
Key:

image_001


Value Pointer:

offset = 100000
size = 200KB


        ↓

Value Log


100000
  |
  v
JPEG Data

这样可以减少大Value参与LSM Compaction的成本。


6.2 Badger适合什么?

特别适合:

text 复制代码
Go服务

大Value

高写入

嵌入式KV

例如:

text 复制代码
Go

↓

Badger

↓

RocksDB风格LSM

第七章 BoltDB / bbolt

Go生态还有一个非常经典的数据库:

bbolt。

它的前身是BoltDB。

核心:

text 复制代码
B+Tree

和LMDB思路比较接近。


7.1 bbolt结构

text 复制代码
Database

       |
       v

     B+Tree
       |
 +-----+-----+
 |           |
Bucket     Bucket

Bucket可以理解成:

text 复制代码
Key Namespace

例如:

text 复制代码
users

images

config

7.2 bbolt与LMDB

两者都属于:

text 复制代码
B+Tree

但是:

text 复制代码
LMDB

重点:

text 复制代码
mmap
Copy-On-Write
MVCC

而:

text 复制代码
bbolt

是Go生态中更加简单直接的嵌入式B+Tree方案。


第八章 SQLite

SQLite 是完全不同于LevelDB的数据库。

它不仅是:

text 复制代码
KV

而是:

text 复制代码
关系型数据库

支持:

text 复制代码
SQL
Table
Index
Transaction
Join
Query

8.1 SQLite底层是什么?

SQLite主要使用:

text 复制代码
B-Tree

进行表和索引的组织。

例如:

text 复制代码
Database

+-------------------+
| Table             |
|                   |
| B-Tree            |
+-------------------+

+-------------------+
| Index             |
|                   |
| B-Tree            |
+-------------------+

8.2 SQLite最大的特点

一个数据库:

text 复制代码
database.db

可以直接复制。

例如:

text 复制代码
app.db

里面:

text 复制代码
用户
配置
历史记录
索引

全部存在一个文件。


8.3 SQLite为什么这么流行?

因为它解决的是:

不需要部署数据库服务器,但又需要完整关系型数据库能力。

例如:

text 复制代码
Android

iOS

Windows桌面

嵌入式设备

浏览器

单机软件

8.4 SQLite vs LMDB

如果数据是:

text 复制代码
Key → Value

而且:

text 复制代码
极致简单

LMDB非常合适。

如果需要:

sql 复制代码
SELECT *
FROM image
WHERE camera_id = 10
AND timestamp > ...

那么:

text 复制代码
SQLite

明显更加合适。


第九章 Berkeley DB

Berkeley DB 是非常经典的嵌入式数据库。

历史非常悠久。

它支持多种数据访问方式:

text 复制代码
B+Tree
Hash
Queue
Recno

因此它不是单纯的:

text 复制代码
B+Tree数据库

而是一个:

多种嵌入式存储结构集合。


9.1 Berkeley DB适合什么?

历史上大量用于:

text 复制代码
嵌入式系统

网络服务

配置数据

缓存

本地数据库

其重要意义在于:

它代表了早期:

text 复制代码
Embedded Database

的经典设计路线。


第十章 Redis

Redis 和LMDB、LevelDB有很大区别。

Redis的核心思想:

数据主要驻留在内存中。


10.1 Redis不是单一数据结构

Redis内部使用多种数据结构。

例如:

text 复制代码
String
Hash
List
Set
Sorted Set
Stream

底层还涉及:

text 复制代码
Hash Table
SkipList
Rax
ZipList / Listpack

10.2 Redis为什么快?

典型路径:

text 复制代码
Client

↓

Redis Server

↓

Memory

↓

Data Structure

而不是:

text 复制代码
Client

↓

Disk

↓

B+Tree

↓

Data

因此:

text 复制代码
访问延迟

非常低。


10.3 Redis为什么还能持久化?

Redis提供:

text 复制代码
RDB
AOF

例如:

text 复制代码
Memory

   |

   +---- RDB
   |
   +---- AOF

所以Redis并不是:

text 复制代码
纯内存 = 数据一定不持久化

而是:

以内存为核心数据层,同时提供持久化机制。


第十一章 WiredTiger

WiredTiger 是MongoDB长期使用的重要存储引擎。

MongoDB:

text 复制代码
Document Database

底层:

text 复制代码
MongoDB
   |
WiredTiger
   |
Storage Engine

11.1 WiredTiger为什么重要?

它代表了一种:

text 复制代码
通用高性能存储引擎

设计。

涉及:

text 复制代码
B-Tree
LSM相关能力
Compression
Cache
Transactions
MVCC

WiredTiger并不能简单概括为"就是一个B+Tree数据库",实际实现包含多个存储和事务机制。


11.2 MongoDB为什么需要独立存储引擎?

因为MongoDB上层解决:

text 复制代码
Document
Query
Aggregation
Replication

而存储引擎解决:

text 复制代码
Page
Index
Transaction
Disk
Cache
Concurrency

于是:

text 复制代码
MongoDB

    |
    v

WiredTiger

    |
    v

Disk

这也是数据库分层架构的重要体现。


第十二章 Pebble

Pebble 是CockroachDB生态中的LSM存储引擎。

它与LevelDB、RocksDB属于同一个思想体系:

text 复制代码
LSM
 |
 +-- MemTable
 +-- WAL
 +-- SSTable
 +-- Compaction

12.1 Pebble为什么出现?

CockroachDB最初大量借鉴RocksDB。

随着自身需求不断发展:

text 复制代码
分布式
事务
Raft
Cloud Native

需要更加贴合自身系统的存储引擎。

于是发展出:

text 复制代码
Pebble

第十三章 TiKV

TiKV 是分布式KV数据库。

它与前面最大的区别:

text 复制代码
LMDB

单机
text 复制代码
LevelDB

单机
text 复制代码
RocksDB

单机存储引擎

而:

text 复制代码
TiKV

分布式KV

13.1 TiKV整体架构

可以理解为:

text 复制代码
                Client
                   |
                   v
                  TiKV
                   |
        +----------+----------+
        |                     |
      Raft                 RocksDB
        |                     |
        v                     v
Replication               Storage

多个TiKV节点:

text 复制代码
Node1
Node2
Node3

通过:

text 复制代码
Raft

保证副本一致性。


13.2 为什么TiKV使用RocksDB思想?

因为:

RocksDB已经很好地解决:

text 复制代码
单机高性能存储

TiKV可以在其基础上增加:

text 复制代码
分布式

Raft

事务

Region

Replication

形成:

text 复制代码
Distributed Database

        +

Local Storage Engine

第十四章 FoundationDB

FoundationDB 的设计思路又有所不同。

它强调:

text 复制代码
Distributed
+
Transactions
+
Ordered Key-Value

可以把它理解成:

text 复制代码
Application

↓

FoundationDB API

↓

Distributed Transaction Layer

↓

Storage Servers

↓

Storage Engine

14.1 FoundationDB最大的特点

不是:

text 复制代码
提供很多SQL语法

而是:

提供一个强一致的、有序Key-Value基础层。

在它之上:

可以构建:

text 复制代码
SQL

Document DB

Metadata Store

Queue

Index

这是一种:

text 复制代码
Database as a Foundation

的思想。


第十五章 B+Tree vs LSM Tree

现在回到整个系列最核心的问题。


B+Tree

text 复制代码
              Root
               |
          +----+----+
          |         |
       Branch     Branch
          |         |
        Leaf      Leaf

数据始终维护在:

text 复制代码
Tree

中。


LSM

text 复制代码
MemTable

   ↓

L0

   ↓

L1

   ↓

L2

   ↓

L3

数据先进入:

text 复制代码
Memory

再不断:

text 复制代码
Merge

第十六章 写入性能

B+Tree

典型:

text 复制代码
Write

↓

Locate Page

↓

Modify Page

↓

Write Page

可能出现:

text 复制代码
Random IO

LSM

text 复制代码
Write

↓

MemTable

↓

Sequential WAL

↓

Flush

因此:

text 复制代码
大量写入

通常更加有优势。


第十七章 读取性能

B+Tree:

text 复制代码
Root

↓

Branch

↓

Leaf

通常只需要:

text 复制代码
O(logN)

并且:

text 复制代码
Key Range

天然适合范围扫描。


LSM:

text 复制代码
MemTable
Immutable
L0
L1
L2
L3

可能需要:

text 复制代码
多个层级
多个SST

所以:

LSM需要Bloom Filter、Block Cache、Index等机制来降低读取成本。


第十八章 Read Amplification

读放大:

为了读取一个用户数据,系统实际读取了多少额外数据。

例如:

text 复制代码
用户需要:

1KB

数据库可能实际:

text 复制代码
读取:

4KB Block

这就是Block级读放大。

LSM还可能:

text 复制代码
MemTable
+
L0
+
L1
+
L2

多个层级检查。


第十九章 Write Amplification

写放大:

text 复制代码
用户写入:

1GB

数据库实际:

text 复制代码
WAL
+
SSTable
+
Compaction
+
Rewrite

最终磁盘可能写:

text 复制代码
3GB
5GB
10GB

这就是:

text 复制代码
Write Amplification

LSM数据库尤其需要关注这一指标。


第二十章 Space Amplification

空间放大:

text 复制代码
用户有效数据:

100GB

磁盘实际:

text 复制代码
150GB

甚至:

text 复制代码
200GB

原因可能包括:

text 复制代码
旧版本
Tombstone
Compaction尚未完成
冗余Block
Index
Bloom Filter

第二十一章 三种放大之间的关系

这是LSM数据库非常重要的概念。

text 复制代码
              Database Performance
                     |
        +------------+------------+
        |            |            |
        v            v            v
   Read Ampl.   Write Ampl.  Space Ampl.
        |            |            |
      读取          写入          空间
        |            |            |
      SSTable     Compaction     Old Data

三者往往存在Trade-off。

例如:

text 复制代码
Compaction更积极

可能:

text 复制代码
Read Amplification ↓

Space Amplification ↓

Write Amplification ↑

因此现代LSM数据库实际上一直在寻找:

读、写、空间三者之间的最佳平衡。


第二十二章 mmap vs Buffer Pool

这是LMDB与传统数据库非常重要的区别。


mmap

LMDB:

text 复制代码
data.mdb

      |
      v

mmap

      |
      v

Virtual Memory

操作系统负责:

text 复制代码
Page Cache
Page Fault
Memory Mapping

Buffer Pool

传统数据库:

text 复制代码
Disk

↓

Buffer Pool

↓

Page

↓

Database

数据库自己管理:

text 复制代码
Page Cache
Eviction
Dirty Page

22.1 两者区别

mmap Buffer Pool
管理者 OS为主 数据库
地址空间 直接映射 数据库控制
数据复制 通常更少 通常存在Page管理
控制能力 较弱 较强
实现 简单 复杂
典型 LMDB SQLite等数据库体系中常见

但是不能简单理解为:

text 复制代码
mmap一定比Buffer Pool快

实际性能取决于:

text 复制代码
工作负载

数据大小

访问模式

内存压力

操作系统

存储设备

第二十三章 SSD时代的数据库

传统观点:

text 复制代码
HDD

随机IO很慢

↓

LSM非常有优势

到了SSD:

text 复制代码
SSD

随机IO变快

那么:

B+Tree是不是就没用了?

不是。


23.1 SSD改变的是成本,而不是原理

SSD依然存在:

text 复制代码
Random IO

Write Amplification

Garbage Collection

Erase Block

尤其NVMe:

text 复制代码
高IOPS
高并发
低延迟

反而使:

text 复制代码
后台Compaction
多线程IO
并发Flush

成为新的优化重点。


第二十四章 HDD、SSD、NVMe对比

可以简单理解:

存储 特点 数据库影响
HDD 随机访问非常昂贵 尽量顺序IO
SATA SSD 随机IO明显提升 LSM/B+Tree均可
NVMe SSD 高IOPS、低延迟 更关注并发和写放大

24.1 HDD

HDD:

text 复制代码
磁头移动
+
盘片旋转

随机:

text 复制代码
Read A
Seek
Read B
Seek
Read C

非常慢。

所以:

text 复制代码
Sequential IO

优势巨大。

LSM Tree非常适合这种思路。


24.2 NVMe

NVMe:

text 复制代码
PCIe
 |
SSD Controller
 |
Flash

可以同时处理大量IO。

于是:

text 复制代码
Compaction

可以使用:

text 复制代码
多个线程
多个IO队列

第二十五章 AI数据集应该选什么?

假设:

text 复制代码
1000万图片

每张:

100KB ~ 5MB

目标:

text 复制代码
训练读取

方案一:LMDB

text 复制代码
图片

↓

LMDB

↓

DataLoader

↓

GPU

非常合适。

尤其:

text 复制代码
写一次

读很多次

方案二:LevelDB

也可以。

但是:

text 复制代码
Compaction

对于大Value并不一定理想。


方案三:RocksDB

适合:

text 复制代码
持续更新

数据不断写入

大规模服务

但如果只是:

text 复制代码
训练集静态读取

LMDB通常更加直接。


第二十六章 日志系统应该选什么?

假设:

text 复制代码
每秒:

100万条日志

核心要求:

text 复制代码
高吞吐
顺序写
后台整理

LSM:

text 复制代码
RocksDB

LevelDB

会更加自然。


第二十七章 缓存系统应该选什么?

如果目标:

text 复制代码
微秒级访问

大量热点数据

TTL

Counter

List

Set

那么:

text 复制代码
Redis

更加适合。

因为:

text 复制代码
数据
 |
Memory

而不是:

text 复制代码
Disk
 |
B+Tree

第二十八章 嵌入式设备应该选什么?

假设:

text 复制代码
工业设备

Windows/Linux

单机

配置数据

状态数据

可以考虑:

text 复制代码
SQLite
LMDB
bbolt

如果需要:

text 复制代码
SQL
复杂查询
关系

选择:

text 复制代码
SQLite

如果:

text 复制代码
Key-Value

读多写少

追求极低读取开销

可以考虑:

text 复制代码
LMDB

第二十九章 Go项目应该选什么?

如果:

text 复制代码
Go

嵌入式KV

可以考虑:

text 复制代码
bbolt
BadgerDB
Pebble

大致:

text 复制代码
B+Tree

    |

  bbolt


LSM

    |

Badger
Pebble

第三十章 分布式数据库应该选什么?

如果已经进入:

text 复制代码
多机器

多副本

故障恢复

一致性

事务

就不应该只考虑:

text 复制代码
LMDB
LevelDB
RocksDB

因为这些本质上主要是:

text 复制代码
Local Storage Engine

需要:

text 复制代码
Raft
Replication
Transaction
Distributed Scheduling

此时可以考虑:

text 复制代码
TiKV

FoundationDB

CockroachDB

第三十一章 Storage Engine与Database的区别

这是非常重要的概念。

很多初学者会把:

text 复制代码
RocksDB

直接理解成:

text 复制代码
完整数据库系统

实际上更准确的是:

text 复制代码
RocksDB

↓

Storage Engine

而:

text 复制代码
TiKV

↓

Distributed Database

↓

RocksDB

同样:

text 复制代码
MongoDB

↓

Database

↓

WiredTiger

↓

Storage Engine

所以可以形成:

text 复制代码
Database
    |
    v
Storage Engine
    |
    v
File System
    |
    v
SSD

第三十二章 数据库的分层

现代数据库大致可以拆成:

text 复制代码
                 Application
                      |
                      v
                  Query Layer
                      |
                      v
                 Transaction
                      |
                      v
                Storage Engine
                      |
          +-----------+-----------+
          |                       |
       Memory                    Disk
          |                       |
    Cache/MemTable          SST/B+Tree
          |                       |
          +-----------+-----------+
                      |
                      v
                  File System
                      |
                      v
                     SSD

如果是分布式数据库:

text 复制代码
                 Client
                   |
                   v
           Distributed Layer
                   |
        +----------+----------+
        |          |          |
       Node       Node       Node
        |          |          |
     Storage    Storage    Storage

第三十三章 为什么没有"最好的数据库"

这是数据库选择中最重要的结论。

因为:

text 复制代码
数据库性能

不是一个单一数字。

必须考虑:

text 复制代码
Read

Write

Latency

Throughput

Space

Consistency

Transaction

Scale

Availability

例如:

LMDB

text 复制代码
Read:

★★★★★

Write:

★★★

Distributed:

☆

RocksDB

text 复制代码
Read:

★★★★

Write:

★★★★★

Distributed:

☆

Redis

text 复制代码
Memory Read:

★★★★★

Memory Write:

★★★★★

Disk Storage:

取决于持久化策略

SQLite

text 复制代码
SQL:

★★★★★

Embedded:

★★★★★

Distributed:

☆

因此:

数据库不是越复杂越好,而是要匹配访问模式。


第三十四章 从访问模式选择数据库

这是比记数据库名字更加重要的方法。


场景一:读多写少

text 复制代码
Read >>> Write

考虑:

text 复制代码
LMDB
B+Tree

场景二:写多读多

text 复制代码
Write ≈ Read

考虑:

text 复制代码
RocksDB
LSM

场景三:超低延迟缓存

text 复制代码
Memory

考虑:

text 复制代码
Redis

场景四:需要SQL

text 复制代码
SQL

考虑:

text 复制代码
SQLite
PostgreSQL
MySQL

而不是:

text 复制代码
RocksDB

然后自己实现SQL。


场景五:分布式KV

text 复制代码
Multi Node

考虑:

text 复制代码
TiKV
FoundationDB

第三十五章 AI/视觉行业数据库选择

结合视觉行业,可以得到一个比较实用的选择表。

数据类型 推荐方案 原因
静态图片数据集 LMDB 读性能好、简单
点云数据集 LMDB / RocksDB 取决于读写比例
Tensor数据集 LMDB 顺序读取方便
推理结果 SQLite 需要查询和统计
实时设备状态 Redis 低延迟
高频日志 RocksDB 高写入
本地配置 SQLite / LMDB 单机嵌入式
大规模分布式KV TiKV 分布式一致性
Go本地KV bbolt / Badger / Pebble Go生态
MongoDB底层 WiredTiger 文档数据库存储引擎

第三十六章 一个工业视觉系统应该如何组合?

实际项目通常不会:

整个系统只选择一种数据库。

而是:

text 复制代码
                Vision System
                     |
       +-------------+-------------+
       |             |             |
       v             v             v
     Redis        SQLite         LMDB
       |             |             |
实时状态          元数据         图片数据
       |
       v
   Device Cache

例如:

text 复制代码
Camera
  |
  +---- Image ------> LMDB/NAS
  |
  +---- Result ------> SQLite
  |
  +---- Status ------> Redis
  |
  +---- Log ---------> RocksDB

这才是实际工程更加常见的架构。


第三十七章 B+Tree与LSM Tree的最终理解

可以用一句话概括:

B+Tree

直接维护最终的数据结构。

text 复制代码
Write
 ↓
Tree
 ↓
Disk

LSM Tree

先接受写入,再通过后台合并维护最终的数据结构。

text 复制代码
Write
 ↓
Memory
 ↓
SST
 ↓
Merge
 ↓
Final State

因此:

text 复制代码
B+Tree:

Write Cost ↑
Read Cost ↓

而:

text 复制代码
LSM:

Write Cost ↓
Read/Compaction Cost ↑

当然,这是总体趋势,不是绝对规律。

现代数据库通过:

text 复制代码
Cache

Bloom Filter

Prefetch

Compaction

Index

Compression

Batch

Parallelism

不断缩小这种差距。


第三十八章 从LMDB到LevelDB,再到RocksDB

整个系列可以串成一条技术发展路线。

text 复制代码
                Database
                   |
          +--------+--------+
          |                 |
          v                 v
       B+Tree             LSM Tree
          |                 |
          v                 v
        LMDB             LevelDB
                            |
                            v
                         RocksDB
                            |
             +--------------+--------------+
             |              |              |
             v              v              v
           TiKV           Pebble        Badger

然后进一步:

text 复制代码
Local Storage Engine
          |
          v
Distributed Database
          |
     +----+----+
     |         |
    TiKV   FoundationDB

第三十九章 现代数据库真正的核心技术

如果从源码和工程角度继续深入,实际上最终会发现:

现代数据库真正重要的是下面这些技术。

text 复制代码
1. B+Tree

2. LSM Tree

3. WAL

4. MVCC

5. Snapshot

6. Copy-On-Write

7. Cache

8. Bloom Filter

9. Compaction

10. Transaction

11. Lock

12. Iterator

13. Serialization

14. Compression

15. Checksum

16. Recovery

17. Concurrency

18. Replication

而:

text 复制代码
LMDB
LevelDB
RocksDB
SQLite
TiKV

只是这些技术不同组合的结果。


第四十章 数据库学习路线

如果希望真正达到:

text 复制代码
能够阅读数据库源码

推荐按照下面的顺序学习。

text 复制代码
第一阶段

Array
Linked List
Hash
Tree
Heap


        ↓


第二阶段

BST
AVL
Red-Black Tree
B Tree
B+Tree


        ↓


第三阶段

Disk IO
Page
Buffer Pool
WAL
Transaction


        ↓


第四阶段

LMDB

B+Tree
mmap
MVCC
Copy-On-Write


        ↓


第五阶段

LSM Tree
SkipList
MemTable
SSTable
Bloom Filter


        ↓


第六阶段

LevelDB


        ↓


第七阶段

RocksDB

Compaction
Cache
Column Family
SSD Optimization


        ↓


第八阶段

Distributed Storage

Raft
MVCC
Replication
Sharding


        ↓


第九阶段

TiKV
FoundationDB
CockroachDB

第四十一章 如果要阅读源码,应该先看什么?

对于C++开发者,建议不要一开始直接阅读整个RocksDB。

可以按照:

text 复制代码
LevelDB

作为入口。

因为LevelDB:

text 复制代码
代码量相对较小
设计思想清晰
核心模块集中

建议阅读顺序:

text 复制代码
DBImpl
  ↓
Write
  ↓
MemTable
  ↓
SkipList
  ↓
WAL
  ↓
VersionSet
  ↓
SSTable
  ↓
Block
  ↓
Iterator
  ↓
Compaction

理解LevelDB之后:

再看:

text 复制代码
RocksDB

会容易很多。


第四十二章 最终总结

整个系列最终可以浓缩成下面这张图:

text 复制代码
                         Key-Value Storage
                                |
                 +--------------+--------------+
                 |                             |
                 v                             v
              B+Tree                         LSM
                 |                             |
        +--------+--------+           +--------+--------+
        |        |        |           |        |        |
       LMDB   SQLite   bbolt       LevelDB  RocksDB  Pebble
        |        |                    |        |
      mmap      SQL                 SSTable   |
        |                           Compaction |
      MVCC                                    |
                                              v
                                             TiKV

而不同数据库实际上是在解决不同的问题:

text 复制代码
LMDB

解决:

如何让嵌入式B+Tree读取非常快?


LevelDB

解决:

如何把随机写转换成顺序写?


RocksDB

解决:

如何把LSM做到高吞吐、高并发、适合SSD?


SQLite

解决:

如何在一个文件里提供完整关系型数据库?


Redis

解决:

如何提供极低延迟的内存数据结构?


TiKV

解决:

如何把KV存储扩展到分布式环境?


FoundationDB

解决:

如何构建强事务、可组合的分布式KV基础设施?

最终应该形成这样一个认知:

数据库不是一堆API,而是一套"数据结构 + 内存管理 + 磁盘布局 + 并发控制 + 事务 + 崩溃恢复"的系统工程。

B+Tree解决的是:

text 复制代码
如何组织磁盘上的有序数据

LSM Tree解决的是:

text 复制代码
如何降低随机写成本

WAL解决的是:

text 复制代码
程序崩溃以后如何恢复

MVCC解决的是:

text 复制代码
读写并发时如何看到一致的数据

Bloom Filter解决的是:

text 复制代码
如何快速判断数据大概率不存在

Compaction解决的是:

text 复制代码
如何把大量SSTable重新整理

Cache解决的是:

text 复制代码
如何减少昂贵的磁盘访问

Raft解决的是:

text 复制代码
多个机器之间如何保持一致

而这些技术组合起来,才形成我们今天看到的:

text 复制代码
SQLite
LMDB
LevelDB
RocksDB
Redis
TiKV
FoundationDB
MongoDB
CockroachDB

因此,真正掌握现代数据库的关键,不是记住:

text 复制代码
"哪个数据库性能最高"

而是看到一个业务需求后能够判断:

text 复制代码
数据规模?
     ↓
读多还是写多?
     ↓
Value大小?
     ↓
是否需要范围查询?
     ↓
是否需要事务?
     ↓
是否需要SQL?
     ↓
是否需要分布式?
     ↓
延迟还是吞吐?
     ↓
HDD / SSD / NVMe?
     ↓
最终选择合适的Storage Engine

这也是从数据结构学习数据库 ,最终走向数据库系统设计的关键一步。

相关推荐
李白客2 小时前
分布式集群与数据库产业:从单机到集群的架构跃迁与市场重构
数据库·分布式·架构
福大大架构师每日一题3 小时前
Redis 8.10.0 正式发布:紧凑哈希、批量导入、备份恢复、流与时序能力全面升级
数据库·redis·哈希算法
雨晨源码(同名B站)3 小时前
基于深度学习YoloV11农业病害虫害检测系统 智慧农业信息化综合管理平台 (附源码+lw文档+ppt)
数据库·人工智能·深度学习·yolo·信息可视化
DBA小马哥4 小时前
向量数据库入门到进阶:Embedding、ANN算法与RAG落地的关键术语
数据库·算法·embedding
云和数据.ChenGuang4 小时前
fastapi项目拆分实战数据模型
java·服务器·数据库·人工智能·深度学习·fastapi·强化学习
祈禾4 小时前
Redis三大特殊数据类型
运维·服务器·数据库·redis·笔记·缓存
东方护航数据恢复(深圳)4 小时前
MySQL_Oracle数据库崩溃修复全攻略_东方护航数据恢复深圳店
数据库·mysql·oracle
y = xⁿ5 小时前
一文掌握Redis常见八股
数据库·redis·缓存
Cloud云卷云舒5 小时前
HaishanDB(海山)|磐维数据库|YashanDB(崖山)深度对比分析
数据库·人工智能·海山数据库·haishandb·移动云海山数据库