# SQL查询性能优化方案
## 优化目标
将`最新运营监控.sql`和`客户维度运营监控.sql`的查询耗时从当前的2分钟降低到30秒以内
## 性能瓶颈分析
当前SQL执行慢的主要原因：
1. **多表关联复杂度高**：存在多次LEFT JOIN、CROSS JOIN，关联数据量较大
2. **重复扫描同一张表**：多个CTE独立扫描`label_scan_history`、`label_replace_requests`表，重复IO开销大
3. **子查询效率低**：部分指标使用EXISTS子查询，逐行判断效率低
4. **索引缺失**：常用关联字段、过滤字段缺少有效索引，查询时全表扫描
5. **计算逻辑重复**：日期转换、维度判断等逻辑在多处重复计算
## 优化方案（按优先级排序）
### 方案一：索引优化（实施成本最低，效果最明显）
#### 需创建的索引：
| 表名 | 索引字段 | 用途 |
|------|----------|------|
| `label_scan_history` | `NeutralWaybillNumber, CreatedAt, Result, Description` | 覆盖扫描记录的关联、过滤、统计需求，避免回表 |
| `label_scan_history` | `CreatedAt, Result, NeutralWaybillNumber` | 覆盖独立统计CTE的统计需求，直接从索引获取统计数据 |
| `label_replace_requests` | `MasterPackageNumber, BillOfLadingNumber, customerid, LabelRetrievedAt` | 覆盖订单表的关联、过滤需求 |
| `arrival_handover_forms` | `HandoverNumber` | 覆盖交接单匹配关联需求 |
| `customers` | `Id, CustomerCode` | 覆盖客户维度关联需求 |
> 所有索引均为组合索引，实现查询全覆盖，避免回表查询
### 方案二：SQL逻辑优化（无额外开发成本，仅修改SQL结构）
1. **合并重复CTE**：将多个独立扫描`label_scan_history`的CTE合并为一个，一次性计算所有扫描相关指标（成功数、失败数、STOP数、扫描数），减少表扫描次数
2. **替换CROSS JOIN**：将`DistinctDates CROSS JOIN OrderFullInfo`改为更高效的关联方式，减少笛卡尔积计算量
3. **移除不必要的逻辑**：删除冗余的判断条件和重复计算逻辑
4. **替换EXISTS子查询**：将指标统计中的EXISTS子查询改为预计算的关联方式
### 方案三：中间汇总表方案（适合准实时场景，性能提升最大）
创建定时任务（每15分钟/每小时执行一次），预计算以下中间结果：
1. `daily_scan_stats`：每日扫描统计结果（日期、扫描数、成功数、失败数、STOP数）
2. `daily_order_stats`：每日订单统计结果（日期、新增换单数、应该换单数、标签推送数等）
3. `customer_daily_stats`：客户维度每日统计结果
查询时直接读取预计算的汇总表，查询耗时可降低到秒级
### 方案四：物化视图方案（适合MySQL 8.0+版本）
创建物化视图预计算常用的统计维度，自动刷新数据，查询时直接读取物化视图
## 实施步骤
### 第一步：先实施索引优化（1小时内完成）
1. 创建上述所有建议的组合索引
2. 重新执行SQL测试性能，预计可降低50%以上的耗时
### 第二步：实施SQL逻辑优化（2小时内完成）
1. 重构SQL结构，合并重复CTE
2. 优化关联逻辑和子查询
3. 测试验证数据准确性和性能提升
### 第三步：（可选）实施中间汇总表方案（半天内完成）
1. 设计汇总表结构
2. 开发定时汇总脚本
3. 修改查询SQL读取汇总表
## 预期效果
- 仅实施索引+SQL逻辑优化：查询耗时可降低到30-60秒
- 实施中间汇总表方案：查询耗时可降低到1-5秒
## 验证标准
1. 查询耗时≤30秒
2. 统计结果和原SQL完全一致
3. 无业务逻辑偏差
