NoSQL数据库
开篇:不是所有数据都适合放进表格
关系型数据库(MySQL、Oracle)用表格存储数据,简单直观。但当你要存社交网络的关系图谱、用户的行为日志、格式不固定的商品属性时,强行往表格里塞就很别扭了。NoSQL(Not Only SQL)就是为这些场景而生的 -- 不是要取代关系型数据库,而是在它不擅长的领域做补充。
NoSQL 四大家族
NoSQL 数据库按数据模型分为四大类,每类解决不同的问题:
| 类型 | 代表产品 | 数据模型 | 典型场景 |
|---|---|---|---|
| 列存储 | HBase | 列族 | 海量数据的随机读写,如日志分析 |
| K-V 存储 | Redis | 键值对 | 高速缓存、会话管理、排行榜 |
| 文档存储 | MongoDB | JSON/BSON 文档 | 内容管理、商品属性、用户画像 |
| 图存储 | Neo4j | 节点 + 边 | 社交网络、知识图谱、推荐系统 |
文档数据库 MongoDB
MongoDB 是 NoSQL 中功能最丰富、最像关系型数据库的。它用 JSON 风格的文档存储数据,天然支持嵌套结构,不需要预先定义表结构。
概念对照
| MySQL | MongoDB | 说明 |
|---|---|---|
| Database | Database | 数据库 |
| Table | Collection | 集合(表) |
| Row | Document | 文档(BSON 格式) |
| Column | Field | 字段 |
| Primary Key | _id | 主键(自动生成) |
| JOIN | Embedded Document | 嵌套文档代替关联 |
BSON 是什么
BSON(Binary JSON)是 MongoDB 的数据格式,和 JSON 类似但是二进制存储。它比 JSON 多了一些数据类型(如 Date、ObjectId),格式是 {key: value},支持嵌套文档和数组。
优点:灵活性高,文档结构可以随时变化。缺点:空间利用率不如关系型数据库。
常用操作
// 插入
db.users.insertOne({ name: "张三", age: 25, tags: ["Java", "Python"] })
// 查询(支持多条件)
db.users.find({ age: { $gte: 18 }, tags: "Java" }).pretty()
// 更新($set 设置字段,$inc 自增)
db.users.updateOne({ name: "张三" }, { $set: { age: 26 }, $inc: { score: 10 } })
// 删除
db.users.deleteMany({ age: { $lt: 18 } })优缺点
| 优点 | 缺点 |
|---|---|
| 文档结构灵活,无需固定 Schema | 不支持传统事务(4.0 之后支持多文档事务) |
| 内置 GridFS,支持大文件存储 | 磁盘占用空间较大 |
| 千万级文档查询性能优秀 | JOIN 能力弱 |
| 水平扩展简单,添加节点即可 | 数据一致性不如关系型数据库 |
图数据库 Neo4j
Neo4j 是开源的图数据库,用节点(Node)和边(Edge) 来存储数据。节点是实体,边是关系。当你需要频繁查询"关系"时(朋友的朋友、商品的关联推荐),图数据库的优势就体现出来了。
为什么关系查询用图数据库更快
以"百万用户社交网络,查朋友的朋友的朋友"为例:
| 查询深度 | MySQL 耗时 | Neo4j 耗时 | 返回记录数 |
|---|---|---|---|
| 2 层 | 0.016s | 0.01s | ~2500 |
| 3 层 | 30s | 0.168s | ~110,000 |
| 4 层 | 1543s | 1.359s | ~600,000 |
| 5 层 | 未完成 | 2.132s | ~800,000 |
深度为 2 时两者差不多,深度为 3 时 MySQL 已经 30 秒(在线系统无法接受),而 Neo4j 不到 1 秒。关系越深,图数据库的优势越明显。
Cypher 查询语言
// 查询林婉儿的伴侣
MATCH (:Person {name:"林婉儿"})-[r:Couple]-(p:Person)
RETURN p.name
// 查三层关系
MATCH data=(a:Person{name:"范闲"})-[*1..3]-(b:Person)
RETURN data
// 查朋友的朋友
MATCH (a:Person{name:"范闲"})-[:Friends]->(b)-[:Friends]->(c)
RETURN a, b, c海量 K-V 存储 Aerospike
Aerospike 是一个分布式 K-V NoSQL 数据库,专为 TB 级别大数据高并发设计。它采用混合架构:索引在内存,数据在 SSD,读写达微秒级。
| 对比项 | Aerospike | Redis |
|---|---|---|
| 定位 | NoSQL 数据库 | 缓存 |
| 线程模型 | 多线程 | 单线程(6.0 后部分多线程) |
| 数据扩容 | 动态增加节点自动均衡 | 需要手动处理 |
| 故障转移 | 设置复制因子后自动故障转移 | 需配置 Sentinel 或 Cluster |
| 存储介质 | 内存(索引)+ SSD(数据) | 纯内存 |
| 99% 延迟 | < 1ms | < 1ms |
Aerospike 主要用在广告行业的个性化推荐场景 -- 将用户画像标签存储在 Aerospike 中,广告投放时实时读取,实现精准投放。
典型推荐链路:用户行为日志 -> ETL 清洗 -> 推荐引擎计算 -> 结果存入 Aerospike -> 广告投放引擎实时读取。
面试高频问答
Q1: NoSQL 数据库有哪些类型?各自适用什么场景?
关键词:四大家族、列存储、K-V、文档、图
列存储(HBase)适合海量数据的随机读写;K-V 存储(Redis)适合高速缓存和简单数据结构;文档存储(MongoDB)适合结构灵活的数据(商品属性、用户画像);图存储(Neo4j)适合关系查询密集的场景(社交网络、知识图谱)。选型的核心依据是数据模型和查询模式。
Q2: MongoDB 和 MySQL 的核心区别?
关键词:文档 vs 行、灵活 Schema、弱 JOIN
MongoDB 用 BSON 文档存储,不需要预定义表结构,字段可以随时增减。MySQL 是严格的表结构,修改需要 ALTER TABLE。MongoDB 的嵌套文档代替了 JOIN,适合层级化数据。但 MongoDB 在事务支持、数据一致性方面不如 MySQL。
Q3: 为什么图数据库查关系比 MySQL 快?
关键词:索引免费邻接、避免多表 JOIN
MySQL 查"朋友的朋友"需要多次 JOIN,深度每加一层就多一次 JOIN,性能指数级下降。图数据库中节点直接通过指针连接邻居(索引免费邻接),遍历关系的时间复杂度和数据总量无关,只和当前节点的关系数有关。所以关系越深、数据量越大,图数据库优势越明显。
小结
NoSQL 不是要取代关系型数据库,而是在特定场景做补充。选型的关键是看数据模型:结构固定用 MySQL,结构灵活用 MongoDB,关系密集用 Neo4j,高速缓存用 Redis,超大容量 K-V 用 Aerospike。很多系统会同时使用多种数据库 -- MySQL 存核心业务数据,Redis 做缓存,ES 做搜索,MongoDB 存日志 -- 这就是所谓的"多模数据库"架构。