当前位置: 首页 > backend >正文

【MySQL】第13节|MySQL 中模糊查询的全面总结

以下是 MySQL 中模糊查询的全面总结,涵盖各种索引优化方案的核心原理、适用场景及操作示例:

一、模糊查询类型与索引优化方案

查询类型示例语法最佳索引方案索引结构适用场景
前缀匹配LIKE 'prefix%'普通索引/前缀索引B-Tree用户名、路径、分类前缀查询
后缀匹配LIKE '%suffix'逆向索引/全文索引B-Tree/倒排索引文件扩展名、URL 后缀查询
任意位置匹配LIKE '%word%'全文索引/搜索引擎(ES)倒排索引文章关键词、内容搜索
函数计算匹配LIKE CONCAT('%', var, '%')函数索引/冗余字段B-Tree动态关键词搜索

二、前缀索引(Prefix Index)

核心原理
  • 索引字段的前 N 个字符,而非全量内容,减少索引体积。
  • 语法
    CREATE INDEX idx_col_prefix ON table_name(column_name(N));
    
适用场景
  • 字段长度较长(如 VARCHAR(255))且前缀重复率低。
  • 查询以固定前缀开头(如 LIKE 'user%')。
操作步骤
  1. 计算最佳 N 值
    SELECT COUNT(DISTINCT LEFT(column_name, N)) / COUNT(*) AS selectivity
    FROM table_name;
    
    • 选择 selectivity 接近 1 的最小 N(通常 ≥ 0.95)。
  2. 创建前缀索引
    CREATE INDEX idx_email_prefix ON users(email(20));
    
优缺点
  • 优点:节省空间,提升前缀匹配性能。
  • 缺点:仅支持前缀匹配,不支持后缀或中间匹配。

三、逆向索引(Reverse Index)

核心原理
  • 将字段值反转后存储,并创建索引,将后缀匹配转化为前缀匹配。
适用场景
  • 查询以固定后缀结尾(如 .jpg.pdf)。
  • 数据量较大且后缀查询频繁。
操作步骤
  1. 添加反转字段
    ALTER TABLE files ADD reversed_path VARCHAR(255) AS (REVERSE(file_path));
    
  2. 创建索引
    CREATE INDEX idx_reversed ON files(reversed_path);
    
  3. 查询时反转条件
    SELECT * FROM files WHERE reversed_path LIKE CONCAT(REVERSE('.jpg'), '%');
    
优缺点
  • 优点:利用 B-Tree 索引优化后缀匹配。
  • 缺点:需额外存储反转字段,查询时需计算 REVERSE()

四、函数索引(Functional Index)

核心原理
  • 直接对表达式或函数结果创建索引,避免查询时重复计算。
适用场景
  • 查询条件包含函数(如 SUBSTRING()LOWER())。
  • 需对计算结果进行过滤(如提取文件扩展名)。
操作步骤
  1. 创建函数索引(MySQL 8.0+):
    CREATE INDEX idx_extension ON files(SUBSTRING_INDEX(file_path, '.', -1));
    
  2. 查询时使用相同函数
    SELECT * FROM files WHERE SUBSTRING_INDEX(file_path, '.', -1) = 'jpg';
    
优缺点
  • 优点:简化查询逻辑,避免手动维护冗余字段。
  • 缺点:索引维护开销大(每次写入需重新计算)。

五、全文索引(Full-Text Index)

核心原理
  • 使用倒排索引结构,将文本分词后建立映射关系,支持高效全文搜索。
适用场景
  • 查询条件可能出现在文本任意位置(如 LIKE '%keyword%')。
  • 需支持自然语言搜索(如权重排序、同义词匹配)。
操作步骤
  1. 创建全文索引
    ALTER TABLE articles ADD FULLTEXT INDEX ft_content(content);
    
  2. 查询语法
    -- 自然语言模式
    SELECT * FROM articles WHERE MATCH(content) AGAINST('keyword');
    -- 布尔模式(支持 + - 等操作符)
    SELECT * FROM articles WHERE MATCH(content) AGAINST('+apple -banana' IN BOOLEAN MODE);
    
配置优化
  • 调整分词参数
    ft_min_word_len = 2  # 最小词长(默认 3)
    ngram_token_size = 2  # 支持中文分词
    
  • 禁用停用词
    ALTER TABLE articles ADD FULLTEXT INDEX ft_content(content) WITH PARSER ngram;
    
优缺点
  • 优点:支持任意位置匹配,性能优于 LIKE '%word%'
  • 缺点:配置复杂,不支持精确位置匹配(如必须在开头)。

六、性能对比与选型建议

索引类型查询效率空间占用维护成本适用场景优先级
前缀索引极高前缀匹配(如用户名、路径)
逆向索引后缀匹配(如文件扩展名)
函数索引需对函数结果过滤的场景
全文索引任意位置模糊匹配(如文章搜索)

七、注意事项与最佳实践

  1. 避免全表扫描
    • 尽量避免 LIKE '%word%'(全表扫描),改用全文索引或 ES。
  2. 索引选择性
    • 对低选择性字段(如性别、状态码)创建索引意义不大。
  3. 覆盖索引
    • 确保查询字段都在索引中,避免回表:
      CREATE INDEX idx_covering ON table_name(column_name) INCLUDE(other_column);
      
  4. 验证索引使用
    EXPLAIN SELECT * FROM table_name WHERE column_name LIKE 'prefix%';
    
    • 检查 type 列是否为 rangeref

八、常见问题排查

  1. 索引未生效
    • 检查查询条件是否包含函数(如 LOWER()),导致索引失效。
    • 使用 FORCE INDEX 强制优化器选择索引:
      SELECT * FROM table_name FORCE INDEX (idx_col) WHERE ...;
      
  2. 全文索引不支持中文
    • 启用 ngram 分词器:
      ALTER TABLE articles ADD FULLTEXT INDEX ft_content(content) WITH PARSER ngram;
      

总结

  • 前缀匹配:优先使用前缀索引(简单高效)。
  • 后缀匹配:逆向索引或全文索引(根据数据量选择)。
  • 任意位置匹配:全文索引或 Elasticsearch(复杂场景)。
  • 函数计算匹配:函数索引或冗余字段(权衡维护成本)。

通过合理选择索引方案,可将模糊查询性能提升数十倍甚至数百倍,避免生产环境出现慢查询瓶颈。

http://www.xdnf.cn/news/10539.html

相关文章:

  • Codeforces Round 1028 (Div. 2)(ABC)
  • JAVA实战开源项目:精简博客系统 (Vue+SpringBoot) 附源码
  • Python打卡训练营Day42
  • 阻塞队列BlockingQueue解析
  • Window系统程序加入白名单
  • LangChain-结合智谱AI大模型实现自定义tools应用实例
  • 吴恩达MCP课程(4):connect_server_mcp_chatbot
  • springboot中@Async做异步操作(Completable异步+ThreadPoolTaskExecutor线程池+@Async注解)
  • shp转3d tiles在cesium渲染楼宇白膜
  • Linux 驱动之设备树
  • Leetcode 2093. 前往目标城市的最小费用
  • SAR ADC 异步逻辑设计
  • Linux系统配置屏幕旋转和触摸旋转
  • 从冷上电到main()函数,Bootloader都做了什么?
  • 数据类型检测有哪些方式?
  • robot_lab学习笔记【MDP综述】
  • QuickJS 如何计算黄金分割率 ?
  • barker-OFDM模糊函数原理及仿真
  • Linux防火墙:全面解析IPTables的表、链、规则!
  • Cypress + TypeScript + Vue3
  • 数据库管理与高可用-MySQL全量,增量备份与恢复
  • 劫持进程注入
  • C语言进阶--程序的编译(预处理动作)+链接
  • 数据结构:递归(Recursion)
  • 基于TMC5160堵转检测技术的夹紧力控制系统设计与实现
  • 输入ifconfig,发现ens33不见了,无法连接至虚拟机
  • Golang——3、流程控制语句
  • C++实现伽罗华域生成及四则运算(三)
  • Python----目标检测(《SSD: Single Shot MultiBox Detector》论文和SSD的原理与网络结构)
  • CppCon 2014 学习:C++ in Huge AAA Games