You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL使用变量查询不走索引触发全表扫描锁表问题求助

根因分析
  • 执行计划生成时无法获取变量值:MySQL的查询优化器在生成执行计划的阶段,用户自定义变量@v_ym的实际值还未完成计算,优化器无法基于ym列的分布统计信息判断走索引的收益更高,因此默认选择全表扫描。
  • 数据类型隐式转换导致索引失效:extract(year_month from ...)返回的是数值类型结果,而表中ym字段定义为varchar(6)字符串类型,二者进行等值比对时,MySQL会自动将ym列的所有字符串值转为数值后再比对,这个转换过程直接导致ym字段的索引无法被命中。
  • 代码笔误:你事件代码中SELECT CAST(@ym AS CHAR);引用的@ym变量并未定义,实际使用的变量是@v_ym,这行冗余代码建议删除。
解决方案

方案1:统一数据类型+强制指定索引

首先将变量转为和ym字段一致的字符串类型,同时查询时强制指定走ym索引,修改后的事件代码如下:

Begin
 SET @v_ym := CAST(extract(year_month from DATE_SUB(SYSDATE(),INTERVAL 1 DAY)) AS CHAR);
 select ssaname,
        @v_ym ym,
        omcr.btscount_ssa(ssaname) btscount,
        sum(case when duration>30 then duration else 0 end) dur_30 
 from btsoutage.bts_faults FORCE INDEX(indx_btsfaults_ym)
 where ym=@v_ym  and ssaname is not null
 group by ssaname;
END;

方案2:使用预处理语句执行查询

预处理语句会在变量值确定后再生成执行计划,可以自动匹配索引,不需要强制指定:

Begin
 SET @v_ym := CAST(extract(year_month from DATE_SUB(SYSDATE(),INTERVAL 1 DAY)) AS CHAR);
 SET @sql = 'select ssaname,? ym,omcr.btscount_ssa(ssaname) btscount,sum(case when duration>30 then duration else 0 end) dur_30 from btsoutage.bts_faults where ym=? and ssaname is not null group by ssaname';
 PREPARE stmt FROM @sql;
 EXECUTE stmt USING @v_ym, @v_ym;
 DEALLOCATE PREPARE stmt;
END;

方案3:直接在条件中写常量计算逻辑

可以不用变量,直接将年月计算逻辑写在WHERE条件中,MySQL的常量折叠机制会提前计算出固定值,生成执行计划时可以正常命中索引:

Begin
 select ssaname,
        extract(year_month from date_sub(sysdate(),interval 1 day)) ym,
        omcr.btscount_ssa(ssaname) btscount,
        sum(case when duration>30 then duration else 0 end) dur_30 
 from btsoutage.bts_faults 
 where ym = DATE_FORMAT(DATE_SUB(SYSDATE(),INTERVAL 1 DAY), '%Y%m') and ssaname is not null
 group by ssaname;
END;

内容的提问来源于stack exchange,提问作者sriman narayana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 21:45:01