存储引擎选型指南

MySQL 用 InnoDB 还是 MyISAM?Redis 选 RDB 还是 AOF?ClickHouse 和 HBase 哪个更适合你的场景?

选错存储引擎,轻则性能下降,重则数据丢失。本指南提供系统的决策框架。

决策框架

选型决策树

业务类型

  ├── OLTP (事务型)
  │     │
  │     ├── 强一致性要求
  │     │     │
  │     │     └── MySQL InnoDB / PostgreSQL
  │     │
  │     └── 最终一致性可接受
  │           │
  │           └── MongoDB / Cassandra

  ├── OLAP (分析型)
  │     │
  │     ├── 实时分析
  │     │     │
  │     │     └── ClickHouse / Druid
  │     │
  │     └── 离线批处理
  │           │
  │           └── Hive / Spark SQL

  └── KV 存储

        ├── 高性能本地存储
        │     │
        │     └── RocksDB / LevelDB

        └── 分布式缓存

              └── Redis / Memcached

按场景选型

OLTP 场景

场景推荐存储理由
电商订单MySQL InnoDB强一致,事务支持好
金融交易PostgreSQL严格的 ACID,MVCC
用户中心MySQL InnoDB读多写少,主键查询
游戏装备Redis Cluster高并发,支持丰富数据结构
社交 FeedMongoDB文档模型灵活

OLAP 场景

场景推荐存储理由
实时大屏ClickHouse高吞吐,低延迟
用户行为分析Druid支持实时摄入,聚合查询
数据仓库Hive/Spark离线批处理,生态完善
日志分析Elasticsearch全文搜索,倒排索引
时序数据InfluxDB/TimescaleDB时序压缩,自动分区

日志与消息

场景推荐存储理由
日志采集Kafka + Elasticsearch高吞吐,支持全文搜索
消息队列持久化RocksDB高写入性能
消息存储Kafka分布式,可回溯
缓存Redis内存级延迟

按数据特征选型

读写比例

读多写少 (90/10):
└── B+ Tree (InnoDB) > 列式存储

写多读少 (10/90):
└── LSM Tree (RocksDB) > B+ Tree

读写均衡 (50/50):
└── 取决于查询复杂度

数据量

数据量推荐存储说明
< 1GBSQLite / MySQL轻量,简单部署
1GB ~ 100GBMySQL InnoDB成熟稳定
100GB ~ 1TBPostgreSQL / MongoDB可扩展
1TB ~ 10TBClickHouse / Elasticsearch列式,高压缩
> 10TBHBase / Cassandra分布式,水平扩展

一致性要求

一致性需求推荐存储说明
强一致 (线性一致)PostgreSQL, MySQL InnoDB分布式事务代价高
最终一致 (可接受延迟)MongoDB, CassandraCAP 取舍
弱一致 (无所谓)Redis, Memcached仅作缓存

主流存储引擎对比

关系型存储

引擎事务并发全文搜索主从复制适用场景
InnoDBACIDMVCC插件异步/半同步OLTP
MyISAM不支持表锁原生异步读多写少
PostgreSQLACIDMVCC插件/GIN逻辑复制OLTP/OLAP
SQLiteACIDWALFTS5文件复制嵌入式

NoSQL 存储

引擎数据模型一致性扩展性适用场景
MongoDB文档可调分片内容管理
Cassandra宽列可调线性时序、消息
HBase宽列强一致分片随机读写
RedisKV/数据结构可调分片/集群缓存、Session

列式存储

引擎压缩率查询性能实时摄入适用场景
ClickHouse极快支持实时分析
Druid支持实时+历史
Parquet极高需转换数据湖
Kudu支持OLAP 混合

存储引擎配置建议

MySQL InnoDB

-- Buffer Pool 足够大(热点数据)
innodb_buffer_pool_size = 75% of RAM

-- Redo Log 足够大
innodb_log_file_size = 1GB  -- (Buffer Pool * 25%)
innodb_log_files_in_group = 3

-- 独立表空间
innodb_file_per_table = ON

-- 刷盘策略
innodb_flush_log_at_trx_commit = 1

RocksDB

Options options = new Options();
options.setWriteBufferSize(64 * 1024 * 1024);  // 64MB MemTable
options.setMaxWriteBufferNumber(3);            // 3 个 MemTable
options.setLevel0FileNumCompactionTrigger(4);  // L0 触发合并
options.setMaxBytesForLevelBase(256 * 1024 * 1024); // L1 256MB
options.setMaxBytesForLevelMultiplier(10);     // 每层 10 倍

ClickHouse

-- MergeTree 表引擎(主表)
CREATE TABLE events (
    event_date Date,
    event_type String,
    user_id UInt32
) ENGINE = MergeTree()
PARTITION BY toYYYYMM(event_date)
ORDER BY (event_type, user_id)
SETTINGS index_granularity = 8192;

-- MaterializedMySQL(实时同步 MySQL)
CREATE TABLE sync_orders AS mysql('host:3306', 'db', 'orders', 'user', 'pass')
ENGINE = MaterializedMySQL('host:3306', 'db');

架构演进建议

小型项目

阶段 1: MySQL 单机
- 数据量 < 100GB
- QPS < 10000
- 单机 MySQL + Redis 缓存

问题: 读写混在一起,缓存命中率低

中型项目

阶段 2: 主从读写分离
- 读: 从库(多个)
- 写: 主库
- 缓存: Redis Cluster

问题: 单机存储瓶颈

大型项目

阶段 3: 分库分表 / NewSQL
- 按业务拆分
- 或迁移到 TiDB / CockroachDB

问题: 跨库查询复杂

超大型项目

阶段 4: 混合架构
- OLTP: MySQL 分库分表 / TiDB
- OLAP: ClickHouse / Druid
- 缓存: Redis Cluster
- 消息: Kafka

实时同步: Canal/Debezium (MySQL → Kafka → ClickHouse)

常见误区

误区一:NoSQL 一定比 SQL 快

NoSQL 在特定场景(高并发写入、海量数据)有优势,但在事务复杂、关联查询多的场景不如关系型数据库。

误区二:缓存越多越好

缓存带来一致性问题和维护复杂度。核心数据不应该过度依赖缓存。

误区三:存储引擎选型一次定终身

数据迁移虽然成本高,但业务发展超出预期时,更换存储引擎是正确的选择。

决策建议:选型前回答三个问题:数据量多大?并发多高?一致性要求多强?答案清晰了,选择就不难了。