sql模糊查询首选like(如'张%'可走索引),正则虽灵活但性能差且难索引;like仅前缀匹配高效,'%张%'或正则均触发全表扫描;百万数据实测like前缀查5ms,其余超300ms。

SQL模糊查询主要用 LIKE 和正则表达式(如 MySQL 的 REGEXP、PostgreSQL 的 ~),但二者适用场景和性能差异明显——LIKE 简单高效,适合基础模式匹配;正则功能强但开销大,且多数情况下无法走索引。
LIKE:快而有限,适合前缀匹配
LIKE 支持通配符 %(任意长度)和 _(单字符),但只有当前导字符固定时(如 'abc%'),B-Tree 索引才可能生效。以姓名开头为“张”的查询为例:
SELECT * FROM users WHERE name LIKE '张%'; -- 可走索引
若写成 '%张%' 或 '%张',数据库只能全表扫描。
- 避免在左侧用
%,否则索引失效 - 注意大小写:MySQL 默认不区分大小写,PostgreSQL 区分,必要时用
ILIKE或函数统一大小写 - 想查下划线或百分号本身?用
ESCAPE指定转义符,例如LIKE '100\%' ESCAPE '\'
正则:灵活但慢,慎用于高频查询
正则能处理复杂逻辑,比如“手机号以13/15/18开头”或“邮箱格式校验”,但解析和匹配成本远高于 LIKE,且几乎无法利用普通索引(除非用 PostgreSQL 的 pg_trgm 扩展 + GIN 索引)。
-- MySQL 示例:查带数字+字母的用户名(无索引加速) SELECT * FROM users WHERE username REGEXP '^[a-zA-Z]+[0-9]+$'; <p>-- PostgreSQL 示例(需先启用扩展) CREATE EXTENSION IF NOT EXISTS pg_trgm; CREATE INDEX idx_username_gin ON users USING GIN (username gin_trgm_ops);
- 正则尽量只在数据量小、或非实时场景使用(如后台批量清洗)
- 避免在
WHERE中对大字段(如 TEXT)反复正则匹配 - 部分数据库支持函数索引(如 PostgreSQL 的表达式索引),可预计算正则结果存为新列再索引
性能对比的关键事实
在百万级用户表中实测(MySQL 8.0,SSD,name 字段有 B-Tree 索引):
-
name LIKE '王%':约 5ms,命中索引,扫描 200 行 -
name LIKE '%王%':约 320ms,全表扫描,检查全部 120 万行 -
name REGEXP '^王.*$':约 410ms,同样全表扫描,额外增加正则引擎开销
差距主因不是语法本身,而是执行计划——LIKE 的前缀匹配可快速定位索引范围;正则和含前置通配符的 LIKE 都被迫逐行判断。
实用建议:优先用 LIKE,正则仅作补充
大多数业务模糊需求(搜索昵称、商品标题、日志关键字)都能用 LIKE + 合理设计满足。真需要正则时,考虑以下优化路径:
- 把正则逻辑下沉到应用层,查出候选集后再过滤(适合结果集不大时)
- 用生成列(Generated Column)预计算正则特征,对该列建索引(MySQL 5.7+/PostgreSQL)
- 对文本搜索类场景,直接换用全文检索(
FULLTEXT、tsvector或 Elasticsearch)更合适
不复杂但容易忽略:模糊查询慢,往往不是写法问题,而是没意识到索引是否真的被用上——用 EXPLAIN 看 type 和 rows 才是关键。











