232 lines
7.6 KiB
SQL
232 lines
7.6 KiB
SQL
-- ================================================
|
||
-- 修复核心性能问题(UPDATE 和 SELECT 慢)
|
||
-- ================================================
|
||
-- 问题:
|
||
-- 1. UPDATE sys_user WHERE user_id = ? 慢(1144ms)
|
||
-- 2. SELECT FROM student_class WHERE student_id = ? 慢(573ms)
|
||
-- 3. SELECT FROM sys_user (JOIN 查询) 慢(575ms)
|
||
-- ================================================
|
||
|
||
USE study;
|
||
|
||
SELECT '========================================' AS '';
|
||
SELECT '修复核心性能问题' AS '';
|
||
SELECT '========================================' AS '';
|
||
|
||
-- ================================================
|
||
-- 1. 检查 sys_user 表结构和索引
|
||
-- ================================================
|
||
|
||
SELECT '' AS '';
|
||
SELECT '【检查1】sys_user 表索引' AS '';
|
||
|
||
SHOW INDEX FROM sys_user;
|
||
|
||
-- 检查 user_id 是否是主键
|
||
SELECT CASE
|
||
WHEN (SELECT COUNT(*) FROM information_schema.STATISTICS
|
||
WHERE TABLE_SCHEMA = 'study' AND TABLE_NAME = 'sys_user'
|
||
AND INDEX_NAME = 'PRIMARY' AND COLUMN_NAME = 'user_id') > 0
|
||
THEN '✅ user_id 是主键'
|
||
ELSE '❌ user_id 不是主键!'
|
||
END AS 'user_id 主键检查';
|
||
|
||
-- 检查 user_name 索引(用于查询是否存在)
|
||
SELECT CASE
|
||
WHEN (SELECT COUNT(*) FROM information_schema.STATISTICS
|
||
WHERE TABLE_SCHEMA = 'study' AND TABLE_NAME = 'sys_user'
|
||
AND COLUMN_NAME = 'user_name') > 0
|
||
THEN '✅ user_name 有索引'
|
||
ELSE '❌ user_name 无索引'
|
||
END AS 'user_name 索引检查';
|
||
|
||
-- ================================================
|
||
-- 2. 检查 student_class 表索引
|
||
-- ================================================
|
||
|
||
SELECT '' AS '';
|
||
SELECT '【检查2】student_class 表索引' AS '';
|
||
|
||
SHOW INDEX FROM student_class;
|
||
|
||
-- ================================================
|
||
-- 3. 检查表的数据量和碎片
|
||
-- ================================================
|
||
|
||
SELECT '' AS '';
|
||
SELECT '【检查3】表数据量和碎片' AS '';
|
||
|
||
SELECT
|
||
TABLE_NAME AS '表名',
|
||
TABLE_ROWS AS '行数',
|
||
ROUND(DATA_LENGTH/1024/1024, 2) AS '数据大小(MB)',
|
||
ROUND(INDEX_LENGTH/1024/1024, 2) AS '索引大小(MB)',
|
||
ROUND(DATA_FREE/1024/1024, 2) AS '碎片大小(MB)',
|
||
CASE
|
||
WHEN DATA_FREE > 0 THEN '⚠️ 有碎片'
|
||
ELSE '✅ 无碎片'
|
||
END AS '碎片状态'
|
||
FROM information_schema.TABLES
|
||
WHERE TABLE_SCHEMA = 'study'
|
||
AND TABLE_NAME IN ('sys_user', 'student_class', 'sys_user_role', 'sys_dept', 'sys_role')
|
||
ORDER BY TABLE_ROWS DESC;
|
||
|
||
-- ================================================
|
||
-- 4. 优化表(清理碎片)
|
||
-- ================================================
|
||
|
||
SELECT '' AS '';
|
||
SELECT '【优化1】清理表碎片...' AS '';
|
||
|
||
OPTIMIZE TABLE sys_user;
|
||
OPTIMIZE TABLE student_class;
|
||
OPTIMIZE TABLE sys_user_role;
|
||
|
||
SELECT '✅ 表优化完成' AS result;
|
||
|
||
-- ================================================
|
||
-- 5. 创建必要的复合索引
|
||
-- ================================================
|
||
|
||
SELECT '' AS '';
|
||
SELECT '【优化2】创建复合索引...' AS '';
|
||
|
||
-- sys_user 表:dept_id 索引(用于 JOIN)
|
||
SELECT '正在检查 sys_user.idx_dept_id...' AS '';
|
||
SET @sql = (SELECT IF(
|
||
(SELECT COUNT(*) FROM information_schema.STATISTICS
|
||
WHERE TABLE_SCHEMA = 'study' AND TABLE_NAME = 'sys_user'
|
||
AND INDEX_NAME = 'idx_dept_id' AND COLUMN_NAME = 'dept_id') = 0,
|
||
'ALTER TABLE sys_user ADD INDEX idx_dept_id (dept_id)',
|
||
'SELECT "idx_dept_id 已存在,跳过" AS result'
|
||
));
|
||
PREPARE stmt FROM @sql;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
-- sys_user 表:del_flag 索引(用于 WHERE u.del_flag = '0')
|
||
SELECT '正在检查 sys_user.idx_del_flag...' AS '';
|
||
SET @sql = (SELECT IF(
|
||
(SELECT COUNT(*) FROM information_schema.STATISTICS
|
||
WHERE TABLE_SCHEMA = 'study' AND TABLE_NAME = 'sys_user'
|
||
AND INDEX_NAME = 'idx_del_flag' AND COLUMN_NAME = 'del_flag') = 0,
|
||
'ALTER TABLE sys_user ADD INDEX idx_del_flag (del_flag)',
|
||
'SELECT "idx_del_flag 已存在,跳过" AS result'
|
||
));
|
||
PREPARE stmt FROM @sql;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
-- sys_dept 表:dept_id 主键应该已存在,检查一下
|
||
SELECT '正在检查 sys_dept 索引...' AS '';
|
||
SELECT CASE
|
||
WHEN (SELECT COUNT(*) FROM information_schema.STATISTICS
|
||
WHERE TABLE_SCHEMA = 'study' AND TABLE_NAME = 'sys_dept'
|
||
AND INDEX_NAME = 'PRIMARY' AND COLUMN_NAME = 'dept_id') > 0
|
||
THEN '✅ sys_dept.dept_id 是主键'
|
||
ELSE '⚠️ sys_dept.dept_id 不是主键'
|
||
END AS result;
|
||
|
||
SELECT '✅ 索引创建完成' AS result;
|
||
|
||
-- ================================================
|
||
-- 6. 重新分析表
|
||
-- ================================================
|
||
|
||
SELECT '' AS '';
|
||
SELECT '【优化3】重新分析表...' AS '';
|
||
|
||
ANALYZE TABLE sys_user;
|
||
ANALYZE TABLE student_class;
|
||
ANALYZE TABLE sys_user_role;
|
||
ANALYZE TABLE sys_dept;
|
||
ANALYZE TABLE sys_role;
|
||
|
||
SELECT '✅ 表分析完成' AS result;
|
||
|
||
-- ================================================
|
||
-- 7. 测试查询性能
|
||
-- ================================================
|
||
|
||
SELECT '' AS '';
|
||
SELECT '【测试】查询性能测试' AS '';
|
||
|
||
-- 测试 UPDATE(实际是测试 WHERE user_id = ?)
|
||
SET @start = NOW(6);
|
||
SELECT * FROM sys_user WHERE user_id = 207 AND del_flag = '0';
|
||
SET @end = NOW(6);
|
||
SELECT
|
||
TIMESTAMPDIFF(MICROSECOND, @start, @end)/1000 AS '用户查询耗时(ms)',
|
||
CASE
|
||
WHEN TIMESTAMPDIFF(MICROSECOND, @start, @end)/1000 < 50 THEN '✅ 优秀'
|
||
WHEN TIMESTAMPDIFF(MICROSECOND, @start, @end)/1000 < 200 THEN '⚠️ 一般'
|
||
ELSE '❌ 较差'
|
||
END AS '性能';
|
||
|
||
-- 测试 student_class 查询
|
||
SET @start = NOW(6);
|
||
SELECT * FROM student_class WHERE student_id = 207 ORDER BY join_time DESC;
|
||
SET @end = NOW(6);
|
||
SELECT
|
||
TIMESTAMPDIFF(MICROSECOND, @start, @end)/1000 AS '班级查询耗时(ms)',
|
||
CASE
|
||
WHEN TIMESTAMPDIFF(MICROSECOND, @start, @end)/1000 < 50 THEN '✅ 优秀'
|
||
WHEN TIMESTAMPDIFF(MICROSECOND, @start, @end)/1000 < 200 THEN '⚠️ 一般'
|
||
ELSE '❌ 较差'
|
||
END AS '性能';
|
||
|
||
-- 测试复杂 JOIN 查询
|
||
SET @start = NOW(6);
|
||
SELECT u.user_id, u.user_name, d.dept_name, r.role_name
|
||
FROM sys_user u
|
||
LEFT JOIN sys_dept d ON u.dept_id = d.dept_id
|
||
LEFT JOIN sys_user_role ur ON u.user_id = ur.user_id
|
||
LEFT JOIN sys_role r ON r.role_id = ur.role_id
|
||
WHERE u.user_id = 207 AND u.del_flag = '0';
|
||
SET @end = NOW(6);
|
||
SELECT
|
||
TIMESTAMPDIFF(MICROSECOND, @start, @end)/1000 AS 'JOIN查询耗时(ms)',
|
||
CASE
|
||
WHEN TIMESTAMPDIFF(MICROSECOND, @start, @end)/1000 < 100 THEN '✅ 优秀'
|
||
WHEN TIMESTAMPDIFF(MICROSECOND, @start, @end)/1000 < 300 THEN '⚠️ 一般'
|
||
ELSE '❌ 较差'
|
||
END AS '性能';
|
||
|
||
-- ================================================
|
||
-- 8. 检查是否有锁表或慢查询
|
||
-- ================================================
|
||
|
||
SELECT '' AS '';
|
||
SELECT '【诊断】检查锁表和慢查询' AS '';
|
||
|
||
-- 检查当前运行的查询
|
||
SELECT
|
||
ID AS '进程ID',
|
||
USER AS '用户',
|
||
HOST AS '主机',
|
||
DB AS '数据库',
|
||
COMMAND AS '命令',
|
||
TIME AS '耗时(秒)',
|
||
STATE AS '状态',
|
||
LEFT(INFO, 50) AS 'SQL前50字符'
|
||
FROM information_schema.PROCESSLIST
|
||
WHERE COMMAND != 'Sleep'
|
||
AND TIME > 1
|
||
ORDER BY TIME DESC
|
||
LIMIT 10;
|
||
|
||
-- ================================================
|
||
-- 完成
|
||
-- ================================================
|
||
|
||
SELECT '' AS '';
|
||
SELECT '========================================' AS '';
|
||
SELECT '✅ 核心性能优化完成!' AS '';
|
||
SELECT '========================================' AS '';
|
||
SELECT '' AS '';
|
||
SELECT '下一步:' AS '';
|
||
SELECT '1. 重启应用服务' AS '';
|
||
SELECT '2. 测试导入10条数据' AS '';
|
||
SELECT '3. 如果仍然慢(UPDATE >500ms),可能是网络问题' AS '';
|
||
SELECT '' AS '';
|