# 数据模型全景(文档 / 图 / 时序 / 向量) ::: tip 🎯 核心问题 **为什么不能把所有数据都塞进 MySQL 的表格里?** 当你的数据是社交关系网、每秒百万条的传感器流水、或者 AI 需要理解的语义向量时,关系型表格就力不从心了。不同的数据形态,需要不同的建模方式。 ::: --- ## 1. 关系型之外:为什么需要其他数据模型? 关系型数据库(MySQL、PostgreSQL)用"表 + 行 + 列"组织数据,适合结构固定、关系明确的业务数据。但现实世界的数据远不止这一种形态: | 数据形态 | 关系型的痛点 | 更合适的模型 | |----------|-------------|-------------| | 用户画像(字段不固定,嵌套结构) | 频繁 ALTER TABLE,大量 NULL 列 | **文档模型** | | 社交网络(朋友的朋友的朋友) | 多层 JOIN 性能指数级下降 | **图模型** | | 监控指标(每秒百万条写入) | 写入瓶颈,历史数据膨胀 | **时序模型** | | AI 语义搜索("意思相近"的内容) | 无法表达语义相似度 | **向量模型** | ::: info 💡 核心观点 不是"替代"关系型,而是"补充"。大多数系统的核心业务仍然跑在 MySQL/PostgreSQL 上,但在特定场景引入专用数据模型,能获得数量级的性能提升。 ::: --- ## 2. 文档模型(Document) ### 2.1 什么是文档模型? 文档模型将数据存储为 **JSON/BSON 文档**,每条记录是一个自包含的文档,可以有不同的字段结构。 ```json { "_id": "user_1001", "name": "张三", "tags": ["VIP", "活跃"], "address": { "city": "北京", "district": "朝阳区" }, "orders": [ { "id": "o1", "amount": 299 }, { "id": "o2", "amount": 599 } ] } ``` **关键特点:** - **无 Schema 约束**:不需要预定义表结构,字段随时增减 - **嵌套结构**:地址、订单直接嵌在文档里,一次读取全部数据 - **水平扩展**:天然适合分片(Sharding),轻松应对海量数据 ### 2.2 文档 vs 关系型 | 对比维度 | 关系型(MySQL) | 文档型(MongoDB) | |----------|----------------|------------------| | 数据结构 | 固定 Schema,ALTER TABLE 修改 | 灵活 Schema,随时加字段 | | 嵌套数据 | 需要多表 JOIN | 直接嵌套在文档中 | | 跨记录关联 | JOIN 很强 | 关联查询较弱 | | 适合场景 | 结构稳定的业务数据 | 结构多变的内容数据 | ### 2.3 典型场景 - **CMS 内容管理**:文章、评论、标签结构各异 - **用户画像**:不同用户有不同的属性字段 - **商品目录**:手机有"屏幕尺寸",食品有"保质期",字段完全不同 - **配置中心**:各服务的配置结构不统一 ::: warning ⚠️ 常见误区 "MongoDB 不需要设计数据结构" —— 错!文档模型同样需要认真设计:嵌套层级不宜过深,频繁更新的子文档应该拆分为独立集合。 ::: --- ## 3. 图模型(Graph) ### 3.1 什么是图模型? 图模型用 **节点(Node)** 和 **边(Edge)** 表达实体及其关系。每个节点是一个实体,每条边是一个关系,节点和边都可以携带属性。 ``` (张三) --[关注]--> (李四) --[关注]--> (王五) | | +--------[购买]----> (iPhone) <--[购买]--+ ``` ### 3.2 图模型的杀手级能力:多跳查询 **场景**:在社交网络中找"朋友的朋友的朋友" 关系型做法(3 层 JOIN): ```sql SELECT DISTINCT f3.name FROM friends f1 JOIN friends f2 ON f1.friend_id = f2.user_id JOIN friends f3 ON f2.friend_id = f3.user_id WHERE f1.user_id = 1001; ``` 图数据库做法(Cypher 查询语言): ```cypher MATCH (me)-[:FOLLOWS*1..3]->(target) WHERE me.name = '张三' RETURN DISTINCT target.name ``` 关系型每多一跳,就多一次 JOIN,性能指数级下降。图数据库通过指针直接遍历关系,多跳查询性能几乎不变。 ### 3.3 典型场景 - **社交网络**:好友推荐、共同关注、影响力传播 - **知识图谱**:实体关系推理("谁是谁的老师的学生") - **欺诈检测**:发现资金环路、关联账户网络 - **推荐系统**:基于用户-商品-标签的关系图推荐 --- ## 4. 时序模型(Time-Series) ### 4.1 什么是时序模型? 时序模型以 **时间戳** 为主轴,专门优化"按时间顺序写入、按时间范围查询"的场景。 ``` timestamp device cpu_usage memory 2024-01-15 10:00:01 server-01 45% 12.3GB 2024-01-15 10:00:02 server-01 67% 12.5GB 2024-01-15 10:00:03 server-01 92% 14.1GB ``` ### 4.2 为什么不用 MySQL 存时序数据? | 问题 | MySQL | 时序数据库(InfluxDB) | |------|-------|----------------------| | 写入速度 | 万级/秒 | **百万级/秒** | | 历史数据 | 手动清理,表越来越大 | **自动过期策略**(TTL) | | 聚合查询 | GROUP BY 慢 | **内置降采样**(5 秒 → 1 分钟均值) | | 存储效率 | 通用存储,空间浪费 | **列式压缩**,节省 90% 空间 | ### 4.3 典型场景 - **服务器监控**:CPU、内存、磁盘每秒采集 - **IoT 传感器**:温度、湿度、GPS 轨迹 - **金融行情**:股票价格、交易量的秒级数据 - **日志分析**:应用日志的时间线聚合 --- ## 5. 向量模型(Vector) ### 5.1 什么是向量模型? 向量模型将文本、图片、音频等非结构化数据通过 **Embedding 模型** 转换为高维数字向量,然后通过计算向量之间的距离来衡量语义相似度。 ``` "好吃的日料" → Embedding → [0.82, 0.15, 0.91, 0.33, ...] ↓ 余弦相似度 "银座寿司之神" → [0.80, 0.18, 0.89, ...] → 96% 相似 "意大利披萨" → [0.12, 0.85, 0.20, ...] → 31% 相似 ``` ### 5.2 向量搜索 vs 关键词搜索 | 对比 | 关键词搜索(LIKE / 全文索引) | 向量搜索 | |------|---------------------------|---------| | 搜索方式 | 精确匹配字符串 | 语义相似度匹配 | | "好吃的日料" | 只能匹配包含"日料"的文本 | 能找到"寿司""刺身""居酒屋" | | 多语言 | 需要分别处理 | 跨语言语义理解 | | 多模态 | 仅文本 | 文本、图片、音频统一检索 | ### 5.3 典型场景 - **RAG(检索增强生成)**:为 LLM 提供相关知识片段 - **语义搜索**:理解用户意图而非关键词 - **以图搜图**:上传一张图,找到视觉相似的图片 - **推荐系统**:基于内容语义的相似推荐 ::: tip 💡 向量数据库的选择 - **独立向量数据库**:Pinecone、Milvus、Weaviate —— 专注向量检索,性能最优 - **传统数据库扩展**:pgvector(PostgreSQL)、Atlas Vector Search(MongoDB)—— 减少架构复杂度 - **内存向量库**:FAISS、Annoy —— 适合小规模、低延迟场景 ::: --- ## 6. 选型决策:如何选择数据模型? | 你的数据长什么样? | 推荐模型 | 代表产品 | |-------------------|---------|---------| | 结构固定,关系明确(订单、用户) | 关系型 | MySQL、PostgreSQL | | 结构灵活,嵌套层级多(内容、配置) | 文档型 | MongoDB、DynamoDB | | 实体之间关系复杂,需要多跳遍历 | 图 | Neo4j、Amazon Neptune | | 按时间顺序写入,按时间范围查询 | 时序 | InfluxDB、TimescaleDB | | 非结构化数据,需要语义相似度搜索 | 向量 | Pinecone、Milvus、pgvector | ::: info 🎯 实战建议 现代系统通常是**多模型混用**: - **核心业务**用 PostgreSQL(关系型) - **用户行为日志**用 InfluxDB(时序) - **AI 知识库**用 Milvus + pgvector(向量) - **推荐引擎**用 Neo4j(图) 不要追求"一个数据库解决所有问题",而是让每种数据找到最合适的家。 :::