You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

MySQL慢查询优化咨询:如何提升特定查询执行效率

优化查询性能的具体方案

针对你遇到的这个查询耗时过长的问题,咱们从当前的执行计划和索引设计入手,一步步来解决:

首先理清楚问题根因:你的查询过滤条件是team_id IS NOT NULL AND end_date IS NULL AND locked = 0,但当前执行计划只用到了ed_idxend_date的单字段索引)。这意味着数据库先用这个索引找到所有end_date IS NULL的记录,之后还要逐条检查另外两个条件,再加上你查询了几乎全表的字段,每次都得回表读取数据,这就是耗时的主要原因。

下面是具体的优化建议:

1. 创建针对性的复合索引

单字段索引在多条件过滤时效率很低,咱们直接创建包含所有过滤条件的复合索引,让数据库能一次性定位到符合要求的记录:

基础优化:优先做过滤型复合索引

先建一个包含三个过滤字段的复合索引,字段顺序建议按选择性从高到低排列(也就是过滤后剩下的记录越少的字段越靠前):

CREATE INDEX idx_end_locked_team ON cm_alloc_spg (end_date, locked, team_id);

你可以先查一下各条件的记录占比来调整顺序——比如如果end_date IS NULL的记录占比最小,就把它放最前面;如果team_id IS NOT NULL的筛选力度更强,也可以把它前置。

进阶优化:用覆盖索引彻底避免回表

如果这个查询的返回字段是固定不变的,那可以直接创建覆盖索引——把查询需要的所有字段都包含到索引里,这样数据库不用回表,直接从索引里就能拿到所有数据,效率会大幅提升:

CREATE INDEX idx_end_locked_team_covering ON cm_alloc_spg (end_date, locked, team_id) INCLUDE (alloc_id, cr_number, profile_id, table_id, provider_id, user_id, trans_reason_id, trans_reason, data_id, trans_fr_provider_id, trans_to_provider_id, from_office_team_id, to_office_team_id, trans_fr_resp_officer_id, trans_to_resp_officer_id, fr_team, to_team, fr_officer, to_officer, start_date, alloc_date, request_type, tr_id, desc_id, `desc`, bd_status_id, active, display_order, created_date, created_by, created_by_user_id, modified_date, modified_by, modified_by_user_id, deleted, deleted_date, deleted_by, deleted_by_user_id, version);

不过要注意,覆盖索引会占用更多磁盘空间,如果你的表有频繁的插入、更新操作,可能会稍微影响写入性能,需要根据实际业务场景权衡。

2. 调整查询语句的小细节

你的查询里写了LIMIT 1000000,但实际只返回32643条记录,这个大LIMIT值虽然不影响结果,但数据库还是会预留处理大结果集的资源,你可以把它改成LIMIT 33000(稍微比实际结果多一点),虽然影响不大,但也算个小优化。另外,如果你有些返回字段实际用不到,记得删掉,减少数据传输和读取的开销。

3. 验证优化效果

创建索引后,一定要重新执行EXPLAIN查看执行计划,确保新的复合索引被用上。如果是覆盖索引,Extra字段会显示Using index;如果是过滤型复合索引,Extra会显示Using index condition; Using where,这样就说明优化生效了。


内容的提问来源于stack exchange,提问作者S. gupta

火山引擎 最新活动