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

7.8 KiB
Raw Blame 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.xmlupdateUser 方法中,字段设置了两次

<!-- 第一次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 行的重复字段设置

修改前:

<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()

修改后:

<if test="studentStatus != null and studentStatus != ''">student_status = #{studentStatus},</if>
update_time = sysdate()

修复2执行数据库优化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重新编译

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导入速度测试

# 导入100条数据
开始时间: 15:30:00
结束时间: 15:30:15
总耗时: 15秒  ✅

# 修复前需要 2-3 分钟
# 修复后只需 15-30 秒

测试3验证SQL正确性

在日志中查看UPDATE SQL应该是

update sys_user
SET dept_id = ?,
    user_name = ?,
    ...
    prison_name = ?,  -- 只出现一次
    prison_area = ?,  -- 只出现一次
    ...
    update_time = sysdate()
where user_id = ?

每个字段只出现一次


⚠️ 注意事项

1. 必须重新编译

Mapper 文件修改后必须重新编译,否则不生效!

mvn clean package -DskipTests

2. 必须重启服务

编译完成后必须重启服务新的Mapper才会加载。

3. 数据库索引

如果没有执行索引SQL性能提升不明显。 建议执行 optimize_import_performance_safe.sql

4. 远程数据库延迟

即使优化后远程数据库仍有网络延迟约50-100ms/条)。 如果需要更快,考虑:

  • 使用本地数据库测试
  • 批量操作
  • 异步处理

🔍 问题根源分析

为什么会有重复字段?

可能的原因:

  1. 代码合并时重复添加
  2. 不同开发者添加相同字段
  3. 复制粘贴时未删除旧代码

为什么慢?

  1. 重复字段: 每个字段设置两次,数据库执行时间翻倍
  2. 缺少索引: 没有索引的查询需要全表扫描
  3. 远程延迟: 网络往返时间增加

💡 优化建议

1. 代码审查

定期检查Mapper文件避免重复字段

# 查找重复的SET语句
grep -A 50 "<update id" mapper/*.xml | grep "SET"

2. 性能监控

启用慢查询日志,及时发现性能问题:

# application.yml
logging:
  level:
    com.ddnai.system.mapper: DEBUG

3. 批量操作

对于大量数据导入,使用批量操作:

// 批量INSERT
mapper.batchInsert(userList);

// 批量UPDATE
mapper.batchUpdate(userList);

📋 检查清单

  • 删除重复字段
  • 重新编译项目
  • 重启服务
  • 执行数据库优化SQL
  • 测试导入100条数据
  • 验证无慢查询警告
  • 确认导入时间正常

总结

核心问题

UPDATE SQL 中字段重复设置两次,导致执行缓慢。

解决方法

删除重复的字段设置351-360行

预期效果

  • UPDATE时间从 1500ms 降到 <100ms
  • 100条导入从 2-3分钟 降到 15-30秒
  • 性能提升15倍以上

关键步骤

  1. 修改Mapper文件
  2. ⚠️ 重新编译
  3. ⚠️ 重启服务
  4. ⚠️ 执行索引SQL如果还没执行

现在重新编译并重启服务,性能应该有显著提升! 🚀