当前位置:首页 >  站长 >  数据库 >  正文

MySQL索引失效的原因:索引按列的原值排序,函数或转换作用在列上就用不上

 2026-11-03 09:12  来源: 互联网   我来投稿 撤稿纠错

  一键部署OpenClaw

一条订单查询从20毫秒涨到1.4秒,46万行的表,order_no上索引建着。EXPLAIN打出来,type是ALL,key那列空的。索引在,优化器不用它。这条SQL上线一年多没动过。最近两周才慢下来,数据量也没暴涨。

索引树按列里存的原值排好序,每一层记的是一段范围。WHERE里写成DATE(created_at) = '2026-10-01',比较的对象变成函数返回值,树上的顺序跟这个值没有对应关系,只能从头扫一遍。把函数挪到等号右侧,改成created_at >= '2026-10-01' AND created_at <= '2026-10-01 23:59:59',列保持原样,索引就能用。SUBSTRING、LEFT、YEAR、MONTH、UNIX_TIMESTAMP包在列外面,性质相同。范围条件可以顺着叶子节点往下走,等值条件能直接定位到那一段。函数把这两条路同时堵住,索引根本用不了。优化器只剩下全表扫描一条路,跟代价高低无关。

另一种是隐式类型转换,两边的类型对不上。order_no在表里是varchar,查询写成WHERE order_no = 20261001001,数字没加引号,MySQL按数值比较,会把列里每个值转成double再比。转换发生在列这一侧,索引直接作废。反过来,int列写成WHERE id = '123',转换落在常量那侧,索引照用。这一条不好记,判断办法是看函数或转换作用在哪一边,只要作用在列上,索引就没戏。手机号、订单号、邮编这类看着像数字的字段,最容易踩。

EXPLAIN里key是NULL、type是ALL、rows接近表的总行数,三个一起出现基本可以定案。possible_keys有值而key为空,说明索引被评估过但没被选中,多半是条件写法的问题。想看得更细,加FORMAT=JSON看代价估算。也可以跑完SHOW WARNINGS,优化器改写后的语句会打出来,函数有没有被搬到常量侧一目了然。

改法按条件类型分。函数包列,就把函数拆到常量那边,日期区间、年份区间都这么写。前导模糊LIKE '%关键字'没有可用前缀,换成全文检索(中文要装ngram分词器),或者把关键词单独建一张检索表。OR两边只有一边有索引,整条语句会退化成全表扫,拆成两条分别查再UNION。联合索引(a,b,c)只按b和c过滤用不上,这是最左前缀的规则,跟写法无关,得单独给b建一条。

MySQL 8.0.13起可以建函数索引,CREATE INDEX idx_d ON orders ((DATE(created_at))),表达式外面套两层括号。建完查询里也得写同样的表达式,改成范围条件反而用不上它。函数索引占空间,写入时还要维护。只在SQL确实改不动的时候用。

改完再跑EXPLAIN,key有值,rows从46万降到三位数,耗时回到20毫秒。上线后把慢查询日志的long_query_time调回1秒。观察2天,同类语句不再冒出来就算收住。你手上要是还有按手机号查、按日期统计的接口,照这个顺序过一遍,比等用户报慢要早。

申请创业报道,分享创业好点子。点击此处,共同探讨创业新机遇!

相关标签
索引失效
mysql

相关文章

  • MySQL 表损坏修复:MyISAM 和 InnoDB 是两套完全不同的打法

    网站某栏目突然打不开,日志里刷Tableismarkedascrashed,或者MySQL莫名重启后某张表查一下就断连——表损坏来了。动手修之前必须先搞清楚一件事:出问题的是MyISAM表还是InnoDB表,两者修法完全不同,用错方法轻则无效,重则把还能救的数据弄没。SHOWTABLESTATUS看

  • MySQL 1040 Too many connections:连接泄漏定位与上限设定

    网站隔三差五报一句数据库连接失败,刷新两下又好了。这种时好时坏的毛病最烦人,因为它不像宕机那样干脆,你没法守在屏幕前等它出现。等到真去查的时候,现场早没了。MySQL从5.7起max_connections默认就是151,8.0也沿用了这个值。超过之后新连接直接被拒,报ERROR1040。看到这个错

  • EXPLAIN结果看不懂?丢给AI要索引优化建议,人工确认再落地

    页面打开慢,查出来是某个SQL拖了后腿。你对MySQL有点基础,知道要看EXPLAIN,但type一列写着ALL,rows几万行,Extra里还有个Usingfilesort——认识每个词,就是不知道从哪下手改。这种时候,AI是个好参谋,但记住它只是参谋,拍板还得你自己来。第一步把证据收集齐:慢SQ

    标签:
    AI编程
    mysql
  • LIMIT 100000,20慢到超时?MySQL深分页的三种解法

    后台导出、爬虫采集、或者用户把列表翻到几千页——只要LIMIT的偏移量上了十万,查询就会肉眼可见地卡。很多人以为是数据太多撑不住,其实是MySQL的工作方式太老实:LIMIT100000,20的意思是把前100020行都取出来,扔掉前100000行,只返回20行。偏移量越大,白干的活越多。先复现确认

    标签:
    php教程
    mysql
  • 千万级大表加索引不敢动?Online DDL和pt-online-schema-change实测

    大表加索引是站长的经典恐惧:ALTERTABLE一执行,表被锁住,网站瞬间打不开,KILL掉还要回滚几小时。以前确实是这样,MySQL5.6之后OnlineDDL成熟了,加索引这类操作可以在线做,执行期间允许并发读写。但“可以在线”不等于“随便什么时候都行”,坑还是有的。OnlineDDL的原理:操

    标签:
    php教程
    mysql

热门排行

信息推荐