网站首页 > 技术文章 正文
生产环境(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中的没效果,保留有效索引并重新命名以便后续区分,无效索引直接删除。
猜你喜欢
- 2025-09-18 怎样实现微软云虚拟机自动关机和开机
- 2025-09-18 设计一个多租户 SaaS 系统,如何实现租户数据隔离(...
- 2025-09-18 让 Agent 拥有长期记忆:基于 Tablestore 的轻量级 Memory 框架实践
- 2025-09-18 分布式微服务中的搜索引擎:架构与实战盘点
- 2025-09-18 设计一个多租户 SaaS 系统,如何实现租户数据隔离与资源配额控制?
- 2025-09-18 设计多租户 SaaS 系统,如何做到数据隔离 & 资源配额?
- 2025-09-18 RAG 写入 —— 怎么把资料放进“书架” (中)
- 2024-08-04 Nacos搭建(nacos搭建集群)
- 2024-08-04 详解mysql常见报错之Failed to add the foreign key constraint
- 2024-08-04 数据库中间件-jdbi(数据库中间件dble)
- 最近发表
- 标签列表
-
- cmd/c (90)
- c++中::是什么意思 (84)
- 标签用于 (71)
- 主键只能有一个吗 (77)
- c#console.writeline不显示 (95)
- pythoncase语句 (88)
- es6includes (74)
- sqlset (76)
- apt-getinstall-y (100)
- node_modules怎么生成 (87)
- chromepost (71)
- flexdirection (73)
- c++int转char (80)
- mysqlany_value (79)
- static函数和普通函数 (84)
- el-date-picker开始日期早于结束日期 (76)
- js判断是否是json字符串 (75)
- c语言min函数头文件 (77)
- asynccallback (87)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- java (73)
- js数组插入 (83)
- mac安装java (72)
- 无效的列索引 (74)