优秀的编程知识分享平台

网站首页 > 技术文章 正文

MySQL 索引优化实战案例_mysql8索引优化

nanyue 2025-09-18 23:52:45 技术文章 1 ℃

生产环境(MySQL5.6)下由于系统是第三方开发,无法对其SQL源码进行调整,捕捉到耗时SQL,通过优化索引的方法进行优化,中间过程26万条记录数据量降到了几千条记录:

该SQL语句主要是从 t_comm_task 表中查询特定条件的任务数据,进行了一些列的字段选择、条件过滤、分组和排序操作。 EXPLAIN 结果显示查询存在一些可能影响性能的问题:

  • 主查询和派生表查询的 type 都是 ALL ,意味着进行了全表扫描,没有有效利用索引,这在数据量较大时会导致查询性能低下。

优化索引建议

1. 针对 WHERE 子句条件建立复合索引

WHERE 子句中有多个条件:

where task.`tenant_id` = 649

and task.worklog_status=30

and task.`valid_flag`=1

and task.real_end_time >= '2025-08-11 12:03:00'

and task.real_end_time <= '2025-08-26 12:03:59'

and task.source_flag in( 0)

为了让这些条件能够有效利用索引,建议创建一个复合索引。索引列的顺序很重要,一般遵循“最左前缀原则”,将选择性高(即取值更离散,重复值少)的列放在前面。可以创建如下复合索引:

CREATE INDEX idx_tenant_status_valid_time_source

ON t_comm_task (tenant_id, worklog_status, valid_flag, real_end_time, source_flag);

这样,MySQL在执行查询时,能够利用这个索引快速过滤出符合条件的记录,减少全表扫描的范围。

2. 考虑 GROUP BY 和 ORDER BY 字段的索引

GROUP BY 和 ORDER BY 部分涉及到多个字段:

group by if(task.batch_id is not null and task.batch_id > 0,task.batch_id,

if(task.part_id is not null and task.part_id > 0,task.part_id,

if(task.mold_id is not null and task.mold_id > 0,task.mold_id,

if(task.ref_id is not null and task.ref_id > 0,task.ref_id,task.task_id)))),

,if(task.work_order_id is not null and task.work_order_id > 0,task.work_order_id,

if(task.section_name ='try' and task.ref_id is not null , task.ref_id, ''))

order by task.`mold_no` ,task.`part_no` ,task.`process_object` ,task.`work_order_no` ,task.`batch_name` asc,

if(task.real_start_time is not null and task.real_start_time > 0,task.real_start_time, task.pre_start_time) desc

由于这里使用了较多的 IF 函数进行条件判断,直接为这些条件创建索引可能比较复杂且效果不一定理想。但可以针对相对固定的排序字段,尝试创建复合索引来辅助排序操作,例如:

CREATE INDEX idx_order_by_fields

ON t_comm_task (mold_no, part_no, process_object, work_order_no, batch_name, real_start_time, pre_start_time);

不过要注意,索引不是越多越好,过多的索引会占用额外的磁盘空间,并且在数据插入、更新和删除时会增加维护索引的开销

3. 检查 NULL 值处理

在SQL中,对 NULL 值的判断和处理可能会影响索引的使用。例如 IFNULL 函数以及 IS NOT NULL 的判断,尽量避免在索引列上使用函数操作,因为这可能导致索引失效。如果可以,在业务逻辑层面处理好 NULL 值,或者调整SQL写法,让索引能够更好地发挥作用。

优化后的验证

在添加索引后,再次使用 EXPLAIN 语句检查执行计划,观察 type 是否从 ALL 变为更优的索引扫描类型(如 range 、 ref 等), rows 预估扫描行数是否减少,以此来判断索引优化是否达到预期效果。

EXPLAIN your_original_sql_statement;

即在待实际执行的SQL语句前再加一个Explain关键词即可

通过以上步骤,有效提升该SQL语句在MySQL 5.6中的查询性能,中间数据量从26万降低多几千条,虽然不一定是最有的,但在生成运行环境下已经非常棒了。以上的考虑方向,where中的索引起效了,group和order中的没效果,保留有效索引并重新命名以便后续区分,无效索引直接删除。

Tags:

最近发表
标签列表