解决问题的秘诀在于思路,这也是需要训练的最重要的能力之一。下面通过复盘一次慢sql解决的过程,争取提炼出某一维度的思路。
SELECT DISTINCT `customers`.* FROM customers as customers WHERE ((customers.user_id in (SELECT `users`.`id` FROM `users` WHERE `users`.`status` = 1 AND `users`.`locked_at` IS NULL AND ((users.path like '0/123456/%'
or users.path = '0/123456')) AND `users`.`deleted_at` IS NULL) or customers.department_id in (1****2))) AND
`customers`.`customer_common_setting_id` IS NULL ORDER BY customers.updated_at desc, `customers`.`id` DESC LIMIT 10 OFFSET 0
执行时长为8秒,相关的两张表数据量都有数百万。
先看整体
看到这条语句居然执行了8秒,实在觉得不可思议,一下子兴趣就更加浓厚。
解构骨架
拿到语句后,首先要做的事情是从整体上梳理出它的结构,然后再逐步进入细节,从整体到局部都有相对清晰的了解。下面来划分一下chunk:
select distinct + 子查询条件 + 其他与/或条件 + 排序 + 分页
可以看出整条语句还是相对简单,是一种很常规的结构。
思考可能的执行计划
清楚结构之后,应该在脑中思考一下可能的执行计划是什么,会用到哪些索引。
查看执行计划
接下来需要做的事情就是查看执行计划了,下面是在测试环境的执行计划:
*************************** 1. row ***************************
id: 1
select_type: PRIMARY
table: customers
partitions: NULL
type: ref
possible_keys: index_customers_on_department_id,index_customers_on_common_setting_id_flow_into_at
key: index_customers_on_co