周日晚上,和小宋在烧烤店聊起了技术面试。他最近一次面试就被问到了一个经典问题:MySQL中LIKE模糊查询如何优化? 这道题确实在数据库面试中频率不低。
要回答这个问题,首先要明白一个核心原则:LIKE查询能否利用索引,很大程度上取决于百分号 % 的位置。
索引使用的基本规则
如果查询字段上建立了索引:
- 后缀匹配能走索引:例如
name LIKE '张%',这种查询可以利用索引进行快速范围扫描,效率很高。
- 前缀匹配不走索引:例如
name LIKE '%明',这种查询会导致索引失效,数据库不得不进行全表扫描。
所以,在日常开发中,应尽量将模糊匹配的符号放在条件末尾。但现实业务往往更复杂,用户可能只记得产品编号的后几位,或姓名的后几个字,这就必须进行前缀模糊匹配。
优化技巧:反向索引
针对必须使用前缀模糊匹配(LIKE '%xxx')的场景,一个巧妙的优化方法是使用反向索引。
其思路是:新增一个字段,用于存储原字段值的反转字符串,并对此新字段建立索引。
举个例子,假设有一个 username 字段,经常需要执行 username LIKE '%son' 这样的查询。
- 新增一个字段
username_reversed。
- 存入原值的反转字符串,例如
'nos'。
- 对
username_reversed 字段建立索引。
此时,原来的 username LIKE '%son' 查询,就可以改写为对反向字段的后缀匹配查询:username_reversed LIKE 'nos%'。后者能够利用索引,从而大幅提升查询效率。
当然,这种方法需要付出额外的存储和维护成本,每次对原字段进行增、删、改操作时,都必须同步更新反向字段。但与全表扫描带来的性能损耗相比,这个代价通常是值得的。
其他优化策略
除了调整索引使用方式,还有其他一些有效的优化手段:
- 结合精确条件缩小范围:在执行
LIKE 查询前,尽可能增加其他等值或范围查询条件,利用这些条件先过滤掉大部分数据,减少 LIKE 操作需要处理的数据集大小。
- 引入缓存层:对于查询非常频繁但数据更新不频繁的场景,可以考虑将查询结果或热点数据缓存到如 Redis 等内存数据库中,直接从缓存响应请求,从而减轻数据库的查询压力。
- 使用全文搜索引擎:对于模糊搜索需求强烈且复杂的场景,终极方案是引入像 Elasticsearch 这样的全文搜索引擎。ES 专为搜索设计,对前后缀模糊匹配、分词搜索等都有极佳的性能支持。常见的架构是将需要模糊查询的字段和主键 ID 同步到 ES,先在 ES 中完成模糊匹配并获取 ID 列表,再根据 ID 回数据库查询完整的行数据。
从遵循基础的索引规则,到巧用反向索引,再到引入缓存和专用搜索引擎,这些方法构成了一套应对不同场景下模糊查询性能问题的完整工具箱。关键在于深入理解其原理,根据实际业务需求和数据特点,灵活选择和组合运用。
|