You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
wx.sstbc.com/数据库索引优化建议.sql

296 lines
11 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

-- ============================================
-- 数据库索引优化建议
-- 基于 coursesHome 统计逻辑分析
-- ============================================
-- ============================================
-- 1. course_signs 表索引
-- ============================================
-- 1.1 核心查询索引status + course_id最常用
-- 用于courseSignsTotal, courseSignsTotalByUnique, getStudentList
-- 查询条件status, course_id, whereHas('course')
ALTER TABLE `course_signs`
ADD INDEX `idx_status_course_id` (`status`, `course_id`);
-- 1.2 用户去重查询索引user_id + status
-- 用于courseSignsTotalByUnique按手机号去重
ALTER TABLE `course_signs`
ADD INDEX `idx_user_id_status` (`user_id`, `status`);
-- 1.3 排除状态索引status用于 whereNotIn status [4,5,6]
-- 注意:如果 status 字段选择性不高,可考虑与 course_id 组合
ALTER TABLE `course_signs`
ADD INDEX `idx_status_not_in` (`status`);
-- 1.4 复合索引status + course_id + user_id用于关联查询优化
ALTER TABLE `course_signs`
ADD INDEX `idx_status_course_user` (`status`, `course_id`, `user_id`);
-- ============================================
-- 2. courses 表索引
-- ============================================
-- 2.1 图表统计索引is_chart + 日期范围
-- 用于getStudentList 中的 whereHas('course')
-- 查询条件is_chart=1, start_date/end_date BETWEEN
ALTER TABLE `courses`
ADD INDEX `idx_is_chart_dates` (`is_chart`, `start_date`, `end_date`);
-- 2.2 课程体系索引type + is_chart
-- 用于:按课程体系筛选课程
ALTER TABLE `courses`
ADD INDEX `idx_type_is_chart` (`type`, `is_chart`);
-- 2.3 复合索引type + is_chart + start_date + end_date
-- 用于:课程分类明细统计
ALTER TABLE `courses`
ADD INDEX `idx_type_chart_dates` (`type`, `is_chart`, `start_date`, `end_date`);
-- ============================================
-- 3. calendars 表索引
-- ============================================
-- 3.1 日期范围查询索引start_time + end_time
-- 用于getCourseTotal, getCourseDayTotal
-- 查询条件start_time/end_time BETWEEN
ALTER TABLE `calendars`
ADD INDEX `idx_dates_range` (`start_time`, `end_time`);
-- 3.2 课程体系索引course_type_id + 日期
-- 用于:按课程体系筛选日历
ALTER TABLE `calendars`
ADD INDEX `idx_course_type_dates` (`course_type_id`, `start_time`, `end_time`);
-- 3.3 统计天数索引is_count_days + 日期
-- 用于getCourseDayTotal开课天数统计
ALTER TABLE `calendars`
ADD INDEX `idx_count_days_dates` (`is_count_days`, `start_time`, `end_time`);
-- 3.4 课程关联索引course_id + course_type_id
-- 用于:通过 course.type 匹配课程体系
ALTER TABLE `calendars`
ADD INDEX `idx_course_type_id` (`course_id`, `course_type_id`);
-- ============================================
-- 4. companies 表索引
-- ============================================
-- 4.1 上市公司索引company_market
-- 用于shangshi, suzhouStock上市公司统计
ALTER TABLE `companies`
ADD INDEX `idx_company_market` (`company_market`);
-- 4.2 被投企业索引is_yh_invested
-- 用于yhInvestedTotal, companyInvestedYear被投企业统计
ALTER TABLE `companies`
ADD INDEX `idx_is_yh_invested` (`is_yh_invested`);
-- 4.3 企业标签索引company_tag用于 LIKE 查询)
-- 用于toubuqiye高新技术企业筛选
-- 注意LIKE '%高新技术企业%' 无法使用索引,但可以优化前缀匹配
ALTER TABLE `companies`
ADD INDEX `idx_company_tag` (`company_tag`(100));
-- 4.4 城市区域索引company_city + company_area
-- 用于area区域统计, isSuzhou苏州筛选
ALTER TABLE `companies`
ADD INDEX `idx_city_area` (`company_city`, `company_area`);
-- 4.5 地址索引company_address用于 LIKE 查询)
-- 用于isSuzhou苏州筛选
-- 注意LIKE '%苏州%' 无法使用索引,但可以优化前缀匹配
ALTER TABLE `companies`
ADD INDEX `idx_company_address` (`company_address`(100));
-- 4.6 复合索引company_market + company_city用于苏州上市公司
ALTER TABLE `companies`
ADD INDEX `idx_market_city` (`company_market`, `company_city`);
-- ============================================
-- 5. users 表索引
-- ============================================
-- 5.1 公司关联索引company_id
-- 用于:通过用户关联公司
ALTER TABLE `users`
ADD INDEX `idx_company_id` (`company_id`);
-- 5.2 跟班学员索引from用于 LIKE 查询)
-- 用于genban, ganbu跟班学员统计
-- 注意LIKE '%跟班学员%' 无法使用索引,但可以优化前缀匹配
ALTER TABLE `users`
ADD INDEX `idx_from` (`from`(50));
-- 5.3 手机号索引mobile用于去重
-- 用于courseSignsTotalByUnique按手机号去重
ALTER TABLE `users`
ADD INDEX `idx_mobile` (`mobile`);
-- 5.4 公司名称索引company_name用于 LIKE 查询)
-- 用于companyJoin元和员工筛选
-- 注意LIKE '%元禾控股%' 等无法使用索引
ALTER TABLE `users`
ADD INDEX `idx_company_name` (`company_name`(100));
-- 5.5 用户地址索引company_address用于 LIKE 查询)
-- 用于isSuzhou苏州筛选
ALTER TABLE `users`
ADD INDEX `idx_user_company_address` (`company_address`(100));
-- 5.6 复合索引company_id + from用于跟班学员筛选
ALTER TABLE `users`
ADD INDEX `idx_company_from` (`company_id`, `from`(50));
-- ============================================
-- 6. stock_companies 表索引
-- ============================================
-- 6.1 上市日期索引stock_date
-- 用于company_market_year_total今年上市公司数量
ALTER TABLE `stock_companys`
ADD INDEX `idx_stock_date` (`stock_date`);
-- 6.2 入学后上市索引is_after_enrollment
-- 用于company_market_after_enrollment_total
ALTER TABLE `stock_companys`
ADD INDEX `idx_after_enrollment` (`is_after_enrollment`);
-- 6.3 公司关联索引company_id
-- 用于:关联 companies 表
ALTER TABLE `stock_companys`
ADD INDEX `idx_company_id` (`company_id`);
-- 6.4 复合索引is_after_enrollment + stock_date
ALTER TABLE `stock_companys`
ADD INDEX `idx_enrollment_date` (`is_after_enrollment`, `stock_date`);
-- ============================================
-- 7. history_courses 表索引
-- ============================================
-- 7.1 日期范围索引start_time + end_time
-- 用于:历史课程统计
ALTER TABLE `history_courses`
ADD INDEX `idx_history_dates` (`start_time`, `end_time`);
-- 7.2 课程类型索引type + 日期
-- 用于:按课程体系筛选历史课程
ALTER TABLE `history_courses`
ADD INDEX `idx_type_dates` (`type`, `start_time`, `end_time`);
-- 7.3 日历关联索引calendar_id
-- 用于whereHas('calendar', is_count_people=1)
ALTER TABLE `history_courses`
ADD INDEX `idx_calendar_id` (`calendar_id`);
-- 7.4 复合索引type + calendar_id + 日期
ALTER TABLE `history_courses`
ADD INDEX `idx_type_calendar_dates` (`type`, `calendar_id`, `start_time`, `end_time`);
-- ============================================
-- 8. course_types 表索引
-- ============================================
-- 8.1 历史课程索引is_history
-- 用于:筛选历史课程类型
ALTER TABLE `course_types`
ADD INDEX `idx_is_history` (`is_history`);
-- 8.2 跟班学员统计索引is_count_genban
-- 用于genban筛选需要统计跟班学员的课程
ALTER TABLE `course_types`
ADD INDEX `idx_is_count_genban` (`is_count_genban`);
-- ============================================
-- 9. 关联查询优化索引
-- ============================================
-- 9.1 course_signs 关联 users 优化
-- 已通过 user_id 索引优化
-- 9.2 users 关联 course_signs 优化
-- 需要在 course_signs 表已有 user_id 索引
-- 9.3 companies 关联 users 优化
-- 需要在 users 表已有 company_id 索引
-- 9.4 courses 关联 course_types 优化
-- 需要在 courses 表已有 type 索引
-- ============================================
-- 10. 特殊查询优化建议
-- ============================================
-- 10.1 JSON 字段查询优化
-- companies.project_users 字段JSON无法直接建立索引
-- 建议:如果 investDate 查询频繁,考虑单独建立 invest_dates 表或字段
-- 10.2 LIKE 查询优化
-- 对于 '%关键词%' 类型的 LIKE 查询,无法使用普通索引
-- 建议:
-- 1. 如果可能,改为前缀匹配 '关键词%' 可以使用索引
-- 2. 考虑使用全文索引FULLTEXT
ALTER TABLE `companies`
ADD FULLTEXT INDEX `ft_company_tag` (`company_tag`);
ALTER TABLE `users`
ADD FULLTEXT INDEX `ft_company_name` (`company_name`);
ALTER TABLE `users`
ADD FULLTEXT INDEX `ft_from` (`from`);
-- 10.3 日期范围查询优化
-- 对于 start_date/end_date BETWEEN 查询,确保日期字段有索引
-- 对于 orWhereBetween 查询MySQL 可能无法同时使用两个索引
-- 建议:如果性能问题,考虑拆分为两个查询 UNION
-- ============================================
-- 11. 索引使用说明
-- ============================================
-- 11.1 索引创建顺序
-- 建议按照表的数据量和查询频率,优先创建高频查询的索引
-- 11.2 索引维护
-- 定期使用 EXPLAIN 分析查询计划,确认索引被正确使用
-- 示例EXPLAIN SELECT * FROM course_signs WHERE status=1 AND course_id IN (1,2,3);
-- 11.3 索引监控
-- 使用以下查询监控索引使用情况:
-- SELECT * FROM sys.schema_unused_indexes;
-- SELECT * FROM performance_schema.table_io_waits_summary_by_index_usage;
-- 11.4 注意事项
-- 1. 索引会占用存储空间,增加写入成本
-- 2. 不要过度索引,每个表建议不超过 5-7 个索引
-- 3. 复合索引的顺序很重要,将选择性高的字段放在前面
-- 4. 定期分析表更新统计信息ANALYZE TABLE table_name;
-- ============================================
-- 12. 性能优化建议
-- ============================================
-- 12.1 查询优化
-- 1. 避免在 WHERE 子句中使用函数
-- 2. 使用 EXISTS 替代 IN当子查询结果集较大时
-- 3. 合理使用 JOIN避免过度嵌套
-- 12.2 分页优化
-- 对于大数据量分页,考虑使用游标分页替代 OFFSET
-- 12.3 缓存策略
-- 对于统计类查询,考虑使用 Redis 缓存结果
-- ============================================
-- 索引创建脚本执行顺序建议
-- ============================================
-- 1. 先创建核心表索引course_signs, courses, calendars
-- 2. 再创建关联表索引companies, users
-- 3. 最后创建辅助表索引stock_companies, history_courses
-- 执行前请备份数据库!
-- 建议在业务低峰期执行索引创建操作