```
开始
↓
需要保留所有明细数据?
├─ 是 → Duplicate Key 表
└─ 否 → 需要聚合(SUM/MAX/REPLACE)?
├─ 是 → Aggregate Key 表(写时聚合,查询快)
└─ 否 → 需要 Key 唯一性?
├─ 是 → 查询频率 >> 写入频率?
│ ├─ 是 → Primary Key 表(MOW,查询最快)
│ └─ 否 → Unique Key 表
│ ├─ MOR(写入频繁)
│ └─ MOW(查询频繁)
└─ 否 → Duplicate Key 表
```
|
表类型 聚合时机 实际情况 Aggregate Key 写时聚合 ✅ 正确 Unique Key 读时或写时(可选) ⚠️ 默认 MOR(读时合并),可配置 MOW(写时去重) Primary Key 写时去重 ✅ 只支持 MOW,性能最优 核心机制 MOR (Merge-On-Read) - 读时合并 写入时:不做处理,直接追加(写入快) 查询时:合并多版本数据(查询慢) 适合: 高频写入、低频查询场景 MOW (Merge-On-Write) - 写时合并 写入时:判断并删除旧数据(写入慢) 查询时:直接读取最新数据(查询快) 适合: 低频写入、高频查询场景 性能对比(数据量大时) 场景 最优选择 高频写入 + 低频查询 Unique Key (MOR) 写入最快 低频写入 + 高频查询 Aggregate Key / Primary Key 查询最快 频繁更新 + 高频查询 Primary Key 综合性能最优 报表统计分析 Aggregate Key 预聚合,存储最小 关键结论 ✅ Primary Key 表性能最优(不是读时聚合,而是写时去重) 查询最快(主键索引优化) 支持删除操作 适合核心业务表 |
#### 查询性能对比 - 表类型 | 写入性能 | 查询性能 | 存储空间 | 数据量:1000 万行 | 数据量:1 亿行 | - --------|---------|---------|---------|-----------------|----------------| - **Duplicate Key** | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | 10 GB | 10 GB | 100 GB | - **Aggregate Key** | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | 1 GB | 1 GB | 10 GB | - **Unique Key (MOR)** | ⭐⭐⭐⭐⭐ | ⭐⭐ | 8 GB(多版本) | 8 GB | 80 GB | - **Unique Key (MOW)** | ⭐⭐⭐ | ⭐⭐⭐⭐ | 2 GB | 2 GB | 20 GB | - **Primary Key (MOW)** | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | 2 GB | 2 GB | 20 GB | **结论:** - **Aggregate Key**:查询最快(已预聚合),存储最小 - **Primary Key**:查询最快(主键索引优化),适合高频查询 - **Unique Key (MOR)**:写入最快,查询慢,适合高频写入场景 #### 场景性能测试 **场景 1:高频写入,低频查询** - 操作 | Duplicate Key | Aggregate Key | Unique Key (MOR) | Primary Key | - 写入 100 万条 | 10 秒 | 15 秒 | 8 秒 ✅ | 12 秒 | - 查询 1 次 | 0.5 秒 | 0.1 秒 | 1.5 秒 | 0.1 秒 | **推荐:** Unique Key (MOR) - 写入最快 --- **场景 2:低频写入,高频查询(报表分析)** - 操作 | Duplicate Key | Aggregate Key | Unique Key (MOR) | Primary Key | - 写入 100 万条 | 10 秒 | 15 秒 | 8 秒 | 12 秒 | - 查询 1000 次 | 500 秒 | 100 秒 ✅ | 1500 秒 | 100 秒 ✅ | **推荐:** Aggregate Key 或 Primary Key - 查询最快 --- **场景 3:频繁更新,高频查询** - 操作 | Duplicate Key | Aggregate Key | Unique Key (MOR) | Unique Key (MOW) | Primary Key | - 更新 10 万条 | 5 秒 | 8 秒 | 2 秒 ✅ | 6 秒 | 5 秒 | - 查询 1000 次 | 500 秒 | 100 秒 ✅ | 1500 秒 | 120 秒 | 100 秒 ✅ | **推荐:** Primary Key - 综合性能最优 |
|
|
|
|
|
|
|
|
|
|
|
在 Doris 中创建表时,**分桶键并不是必须指定的**。这取决于你所选择的分桶方式:
* **✅ 使用 Random 分桶**:**不需要指定分桶键**。数据会随机、均匀地分布到各个分桶中,可以有效避免数据倾斜。
* **🔑 使用 Hash 分桶**:**必须指定分桶键**。你需要选择一列或多列作为分桶键,Doris会根据这些列的Hash值将数据分配到不同的分桶中。
> **提醒**:Random 分桶仅适用于 `DUPLICATE KEY`(明细模型)表,`UNIQUE`(主键/唯一模型)和 `AGGREGATE`(聚合模型)表**不能**使用 Random 分桶。
### 📝 两种分桶方式对比
**Hash 分桶** (`DISTRIBUTED BY HASH(...)`)
* **分桶键**:**必须指定**
* **适用表模型**:DUPLICATE、UNIQUE、AGGREGATE
* **适用场景**:有频繁作为过滤条件的高基数列(如 `user_id`),或需要进行高并发点查。
**Random 分桶** (`DISTRIBUTED BY RANDOM`)
* **分桶键**:**不需要指定**
* **适用表模型**:仅 `DUPLICATE KEY`(明细模型)
* **适用场景**:没有固定的过滤条件,或分桶键列数据分布不均,担心手动选错列导致数据倾斜。
### 💎 选择建议
总的来说,如果业务场景明确,有高频使用的过滤字段(如用户ID、订单ID),选择 **Hash 分桶**并正确指定分桶键,可以获得最佳的查询性能。
如果数据导入频繁且对数据均匀分布的要求高于特定列的查询剪裁,那么对于明细模型表来说,**Random 分桶**是一个简单且有效的选择。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|