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

Go/MySQL中预编译语句用LIKE '%'与动态生成SQL哪种性能更优

Go/MySQL 列表查询方案选型结论

优先选择动态拼接WHERE条件+参数绑定值的方案,不推荐使用固定预编译语句+未传参填充LIKE '%'的写法。

关于LIKE '%'的性能开销真相

在你描述的预编译参数绑定场景下,LIKE '%'的性能开销是明确存在的,且数据量越大越明显,核心原因如下:

  • 预编译语句的执行计划在prepare阶段就会生成,此时占位符?对应的实际值还未传入,优化器看到的只是attr LIKE ?的条件结构,根本不知道后续绑定的是会匹配全量值的'%',还是能走前缀索引的'xxx%',或是完全无法走B树索引的'%xxx'。这种情况下优化器只能生成非常保守的执行计划,大概率无法正确命中你为对应列建好的索引,甚至可能选错驱动表、选错索引,导致查询性能出现数量级的下降。
  • 执行阶段引擎会对每一行数据都做一次LIKE匹配判断,哪怕绑定值是'%'导致结果全为true,这个逐行判断的CPU开销在表数据量达到十万级以上时就会非常明显。

常见认知误区:很多人以为LIKE '%'是恒真条件就不会产生额外开销,这个结论仅对硬编码写死在SQL语句中的LIKE '%'生效——此时优化器会在解析阶段做常量折叠,直接移除这个多余条件。但预编译参数绑定场景下,占位符的值是执行阶段才传入的,优化器在生成执行计划时根本看不到实际传入的'%',完全无法做这个优化,逐行匹配的开销会真实存在。

  • 当你同时传入多个筛选参数时,固定的多LIKE条件结构会让优化器更难判断索引选择的优先级,进一步放大执行计划选错的概率。

两种方案的实际开销对比

你担心的动态生成SQL的解析开销,在实际生产场景下几乎可以忽略,远小于固定预编译+LIKE '%'方案的性能损耗:

  • 动态拼接SQL不需要为每一种参数组合单独做预编译:只要你遵循「动态拼条件结构,所有参数值用占位符绑定」的原则(绝对不要直接把用户传入的值拼到SQL字符串里,避免SQL注入),相同结构的SQL(比如只带attr筛选、同时带attr和attr2筛选)在第一次执行后,会被MySQL服务端的语句缓存、Go侧MySQL驱动(如go-sql-driver/mysql)的客户端预编译缓存自动留存,后续相同结构的查询直接复用执行计划,不会重复做全量SQL解析。
  • 动态拼接生成的SQL,WHERE子句里只保留实际生效的筛选条件,优化器可以根据明确的过滤条件选择最优索引,查询本身的执行效率会远高于带一堆恒真LIKE条件的固定SQL,这部分执行阶段的性能收益,比SQL解析的那点开销高几个数量级。
  • 哪怕你有10个可筛选字段,实际业务中常用的筛选组合最多也就几十种,远远达不到撑爆语句缓存的程度,完全不需要担心预编译覆盖不全的问题。

落地实操建议

  • 先给所有支持筛选的字段建白名单,只有命中白名单的查询参数才允许被拼接到SQL中,从根源上避免非法字段查询和SQL注入风险。
  • 拼接条件时,每新增一个筛选规则就对应加一个?占位符,用户传入的参数值单独按顺序传给驱动执行,不要直接拼入SQL字符串。如果要做前缀匹配,在业务侧给参数值补上后缀通配符即可(比如用户传val,绑定值设为val%,即可命中对应列的B树前缀索引),不要允许用户自定义传入通配符,避免出现%val这种无法走索引的查询。
  • 不要为了图代码写起来简单就用固定SQL+LIKE '%'的方案,这类写法在小数据量测试时看不出问题,等业务数据量涨到百万级以上很容易出现慢查询故障。

内容的提问来源于stack exchange,提问作者sgt-hartman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 07:57:28