guoyu/_已清理文件备份_周六 22512/md/UPDATE慢查询问题修复.md
2025-12-06 20:11:36 +08:00

325 lines
7.8 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# UPDATE 慢查询问题修复
## ❌ **问题现象**
导入100条数据需要很长时间每条UPDATE需要1.5-1.6秒。
### **日志显示**
```
slow sql 1608 millis. update sys_user
slow sql 1577 millis. update sys_user
slow sql 1160 millis. update sys_user
```
**预期时间:** <100ms
**实际时间:** 1500ms+
**慢了15倍**
---
## 🔍 **问题原因**
### **原因1UPDATE SQL 字段重复设置(最严重)**
`SysUserMapper.xml` `updateUser` 方法中字段设置了**两次**
```xml
<!-- 第一次340-350行 -->
<if test="prisonName != null and prisonName != ''">prison_name = #{prisonName},</if>
<if test="prisonArea != null and prisonArea != ''">prison_area = #{prisonArea},</if>
<if test="ethnicity != null and ethnicity != ''">ethnicity = #{ethnicity},</if>
<if test="educationLevel != null and educationLevel != ''">education_level = #{educationLevel},</if>
<if test="crimeName != null and crimeName != ''">crime_name = #{crimeName},</if>
<if test="sentenceTerm != null">sentence_term = #{sentenceTerm},</if>
<if test="sentenceStartDate != null">sentence_start_date = #{sentenceStartDate},</if>
<if test="sentenceEndDate != null">sentence_end_date = #{sentenceEndDate},</if>
<if test="entryDate != null">entry_date = #{entryDate},</if>
<if test="studentStatus != null and studentStatus != ''">student_status = #{studentStatus},</if>
<!-- 第二次351-360行重复 -->
<if test="prisonName != null">prison_name = #{prisonName,jdbcType=VARCHAR},</if>
<if test="prisonArea != null">prison_area = #{prisonArea,jdbcType=VARCHAR},</if>
<if test="ethnicity != null">ethnicity = #{ethnicity,jdbcType=VARCHAR},</if>
<if test="educationLevel != null">education_level = #{educationLevel,jdbcType=VARCHAR},</if>
<if test="crimeName != null">crime_name = #{crimeName,jdbcType=VARCHAR},</if>
<if test="sentenceTerm != null">sentence_term = #{sentenceTerm,jdbcType=INTEGER},</if>
<if test="sentenceStartDate != null">sentence_start_date = #{sentenceStartDate,jdbcType=DATE},</if>
<if test="sentenceEndDate != null">sentence_end_date = #{sentenceEndDate,jdbcType=DATE},</if>
<if test="entryDate != null">entry_date = #{entryDate,jdbcType=DATE},</if>
<if test="studentStatus != null and studentStatus != ''">student_status = #{studentStatus},</if>
```
**结果:** 每个字段都被设置了两次导致UPDATE执行缓慢
---
### **原因2数据库索引未创建**
执行 `optimize_import_performance_safe.sql` 添加索引提升查询速度
---
### **原因3远程数据库延迟**
数据库在远程服务器 `101.35.101.159`存在网络延迟
---
## ✅ **解决方案**
### **修复1删除重复字段已完成**
**文件:** `SysUserMapper.xml`
**修改:** 删除 351-360 行的重复字段设置
**修改前:**
```xml
<if test="studentStatus != null and studentStatus != ''">student_status = #{studentStatus},</if>
<if test="prisonName != null">prison_name = #{prisonName,jdbcType=VARCHAR},</if>
<if test="prisonArea != null">prison_area = #{prisonArea,jdbcType=VARCHAR},</if>
<!-- ...更多重复字段... -->
<if test="studentStatus != null and studentStatus != ''">student_status = #{studentStatus},</if>
update_time = sysdate()
```
**修改后:**
```xml
<if test="studentStatus != null and studentStatus != ''">student_status = #{studentStatus},</if>
update_time = sysdate()
```
---
### **修复2执行数据库优化SQL**
如果还没执行请执行
```sql
-- 文件log/Sql/optimize_import_performance_safe.sql
-- 主要添加以下索引:
ALTER TABLE sys_user ADD INDEX idx_user_name (user_name);
ALTER TABLE sys_user ADD INDEX idx_nick_name (nick_name);
ALTER TABLE student_class ADD INDEX idx_student_id (student_id);
ALTER TABLE student_class ADD INDEX idx_student_status (student_id, status);
```
---
## 🚀 **部署步骤**
### **步骤1重新编译**
```bash
cd C:\Users\Administrator\Desktop\Project\ry_study-v_03\Study-Vue-redis
mvn clean package -DskipTests
```
### **步骤2重启服务**
停止旧服务启动新服务
### **步骤3执行数据库优化如果还没执行**
Navicat 中连接到数据库 `study`执行
```
log/Sql/optimize_import_performance_safe.sql
```
### **步骤4测试导入**
1. 导入100条数据
2. 观察日志查看UPDATE时间
3. 确认无 "slow sql" 警告
---
## 📊 **性能对比**
### **修复前**
| 指标 | 数值 |
|------|------|
| 每条UPDATE时间 | 1500ms+ |
| 100条总时间 | 2-3分钟 |
| 慢查询警告 | 每条都有 |
| SQL字段 | 重复设置 |
### **修复后(预期)**
| 指标 | 数值 |
|------|------|
| 每条UPDATE时间 | <100ms |
| 100条总时间 | 10-30秒 |
| 慢查询警告 | |
| SQL字段 | 正常 |
**性能提升15倍以上**
---
## 🧪 **验证方法**
### **测试1查看SQL执行时间**
导入时查看日志应该看到
```
DEBUG c.d.s.m.S.updateUser - ==> Preparing: update sys_user SET ...
DEBUG c.d.s.m.S.updateUser - ==> Parameters: ...
DEBUG c.d.s.m.S.updateUser - <== Updates: 1
```
**不应该有** "slow sql" 警告
---
### **测试2导入速度测试**
```bash
# 导入100条数据
开始时间: 15:30:00
结束时间: 15:30:15
总耗时: 15秒 ✅
# 修复前需要 2-3 分钟
# 修复后只需 15-30 秒
```
---
### **测试3验证SQL正确性**
在日志中查看UPDATE SQL应该是
```sql
update sys_user
SET dept_id = ?,
user_name = ?,
...
prison_name = ?, -- 只出现一次
prison_area = ?, -- 只出现一次
...
update_time = sysdate()
where user_id = ?
```
每个字段**只出现一次**
---
## ⚠️ **注意事项**
### **1. 必须重新编译**
Mapper 文件修改后必须重新编译否则不生效
```bash
mvn clean package -DskipTests
```
### **2. 必须重启服务**
编译完成后必须重启服务新的Mapper才会加载
### **3. 数据库索引**
如果没有执行索引SQL性能提升不明显
建议执行 `optimize_import_performance_safe.sql`
### **4. 远程数据库延迟**
即使优化后远程数据库仍有网络延迟约50-100ms/)。
如果需要更快考虑
- 使用本地数据库测试
- 批量操作
- 异步处理
---
## 🔍 **问题根源分析**
### **为什么会有重复字段?**
可能的原因
1. 代码合并时重复添加
2. 不同开发者添加相同字段
3. 复制粘贴时未删除旧代码
### **为什么慢?**
1. **重复字段:** 每个字段设置两次数据库执行时间翻倍
2. **缺少索引:** 没有索引的查询需要全表扫描
3. **远程延迟:** 网络往返时间增加
---
## 💡 **优化建议**
### **1. 代码审查**
定期检查Mapper文件避免重复字段
```bash
# 查找重复的SET语句
grep -A 50 "<update id" mapper/*.xml | grep "SET"
```
### **2. 性能监控**
启用慢查询日志及时发现性能问题
```yaml
# application.yml
logging:
level:
com.ddnai.system.mapper: DEBUG
```
### **3. 批量操作**
对于大量数据导入使用批量操作
```java
// 批量INSERT
mapper.batchInsert(userList);
// 批量UPDATE
mapper.batchUpdate(userList);
```
---
## 📋 **检查清单**
- [x] 删除重复字段
- [ ] 重新编译项目
- [ ] 重启服务
- [ ] 执行数据库优化SQL
- [ ] 测试导入100条数据
- [ ] 验证无慢查询警告
- [ ] 确认导入时间正常
---
## ✅ **总结**
### **核心问题**
UPDATE SQL 中字段重复设置两次导致执行缓慢
### **解决方法**
删除重复的字段设置351-360行)。
### **预期效果**
- UPDATE时间从 1500ms 降到 <100ms
- 100条导入从 2-3分钟 降到 15-30秒
- **性能提升15倍以上**
### **关键步骤**
1. 修改Mapper文件
2. 重新编译
3. 重启服务
4. 执行索引SQL如果还没执行
---
**现在重新编译并重启服务,性能应该有显著提升!** 🚀