guoyu/Test/备份/_已清理文件备份_周六 22512/md/UPDATE慢查询问题修复.md

325 lines
7.8 KiB
Markdown
Raw Normal View History

# 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如果还没执行
---
**现在重新编译并重启服务,性能应该有显著提升!** 🚀