MySQL 单表访问方法详解

news/2025/2/24 17:34:38

单表访问

  • MySQL 单表访问方法详解:高效查询之道
      • **一、 查询执行基础**
      • **二、 访问方法 (Access Method) 概念**
      • **三、 具体访问方法 (从最优到最差)**
      • **四、 注意事项**
      • **五、 总结与优化建议**
      • **六、 电商网站数据存储应用示例**
      • **七、 数据备份与恢复模型 (补充)**

MySQL 单表访问方法详解:高效查询之道

核心思想: MySQL 执行单表查询的目标是尽可能高效地从表中获取所需数据。访问方法(Access Method)决定了 MySQL 如何扫描表中的记录,是全表扫描还是利用索引,直接影响查询性能。理解并选择合适的访问方法是查询优化的基础。

一、 查询执行基础

  • 查询优化器****与执行计划: MySQL Server 中的查询优化器解析查询语句后生成执行计划。执行计划决定了使用哪些索引、表的连接顺序等。存储引擎根据执行计划执行查询并返回结果。理解查询执行原理是优化慢查询的关键。

  • 单表查询: 本文聚焦于单表查询(FROM 子句后只有一个表),这是最基础的查询类型。

二、 访问方法 (Access Method) 概念

访问方法是指 MySQL 访问表数据的方式,决定了查询优化器选择哪种策略检索数据。

  • 全表扫描 (ALL): 逐行扫描所有记录。适用于无索引或查询条件无法利用索引的情况,效率低,尤其对于大表。

  • 索引访问: 利用索引快速定位数据。包括针对主键/唯一索引的等值查询、普通二级索引的等值查询、索引列的范围查询以及索引全扫描等。

三、 具体访问方法 (从最优到最差)

以下访问方法按效率从高到低排序,类似于查询优化器选择路径的优先级:

  1. const (或 system):常数级别访问
  • 原理: 使用主键 (PRIMARY KEY) 或唯一二级索引 (UNIQUE INDEX) 与常数进行等值匹配,且最多返回一条记录。systemconst 的特例,表只有一行记录时使用。

  • 机制: B+ 树索引快速查找,直接定位。由于索引的有序性,查找接近 O(1)。查询优化器预先计算索引查找路径。

  • 应用场景: 根据用户 ID (主键) 查用户信息;根据唯一订单号 (唯一索引) 查订单。

  • 性能: 极速,少量 I/O。

  • 示例:


SELECT * FROM users WHERE id = 1; -- id 是主键

SELECT * FROM orders WHERE order_no = 'unique_123'; -- order_no 是唯一索引

限制 :仅适用于主键列或唯一二级索引列与常数的等值比较,且当唯一二级索引列值为 NULL 时不可用此方法。

  1. eq_ref:唯一索引等值引用 (连接查询)
  • 原理: 连接查询中,被驱动表通过主键或唯一二级索引等值匹配访问,且保证对于驱动表的每条记录,被驱动表最多只返回一条匹配记录。

  • 机制: 索引关联,驱动表结果驱动被驱动表查询。被驱动表通过唯一索引快速查找。

  • 应用场景: 订单表和用户表关联,通过用户 ID (用户表主键) 关联订单表;一对一关联。

  • 性能: 高效,少量 I/O。

  • 示例:


SELECT o.*, u.* FROM orders o JOIN users u ON o.user_id = u.id WHERE o.order_id = 100; -- users.id 是主键

  1. ref:非唯一索引等值引用
  • 原理: 使用非唯一二级索引进行等值匹配,可能返回多条记录。

  • 机制: 索引范围扫描,找到多条索引记录。ref 是等值匹配 ( =, IN),range 是范围匹配 (>, <, BETWEEN)。

  • 应用场景: 根据商品分类 ID (非唯一索引) 查商品;根据用户角色 (非唯一索引) 查用户。

  • 性能: 比全表扫描高效,但不如 consteq_ref

  • 示例:


SELECT * FROM products WHERE category_id = 5; -- category_id 是非唯一索引

注意事项 :若二级索引列值为 NULL,只能使用 ref 访问方法而非 const;对于联合索引,只要最左边的连续索引列与常数等值比较就可能采用 ref 方法,否则不能称为 ref。

  1. fulltext:全文索引
  • 原理: 查询条件涉及MATCH AGAINST语法,且使用全文索引。

  • 机制: 基于倒排索引,将文本拆分成词语并记录。支持相关性排序(如 TF-IDF 或 BM25)。

  • 应用场景: 商品搜索(根据名称、描述);博客文章搜索(根据标题、内容)。

  • 性能: 针对文本搜索优化,比LIKE '%keyword%'效率高。

  • 示例:


SELECT * FROM articles WHERE MATCH(title,content) AGAINST ('MySQL 优化');

  1. ref_or_null:索引等值引用或 NULL
  • 原理: 类似于 ref,但多了对 NULL 值的处理。查询条件是索引列等值匹配 + IS NULL

  • 机制: 先索引等值查找 (同 ref),再扫描索引的 NULL 值记录。索引列需允许 NULL。

  • 应用场景: 查询非必填字段为特定值或为空的记录。

  • 性能: 略低于 ref

  • 示例:


SELECT * FROM users WHERE email = 'test@example.com' OR email IS NULL; -- email 有索引且允许 NULL

  1. index_merge:索引合并
  • 原理: 一个表可以使用多个索引完成查询,MySQL 将多个索引扫描结果合并。

  • 机制: 优化器判断可使用多个索引分别过滤,合并结果 (Intersection, Union, Sort-Union)。

  • index_merge_intersection: 索引求交集 (AND)。

  • index_merge_union: 索引求并集 (OR)。

  • index_merge_sort_union: 先排序,再求并集。

  • 应用场景: 复杂查询条件,可使用多个索引独立过滤。

  • 性能: 通常优于全表扫描,但取决于索引选择性和合并策略。不当使用可能比单个索引低效。

  • 示例:

Intersection 合并 示例:查询 single_table 表中 key1 = ‘a’ AND key3 = ‘b’ 的记录,可使用 idx_key1 和 idx_key3 索引进行 Intersection 合并。此外,主键列可进行范围匹配的情况也可使用此合并方法。

Union 合并 示例:查询 single_table 表中 key1 = ‘a’ OR key3 = ‘b’ 的记录,可使用 idx_key1 和 idx_key3 索引进行 Union 合并。

Sort-Union 合并 示例:查询 single_table 表中 key1 < ‘a’ OR key3 > ‘z’ 的记录,可使用 idx_key1 和 idx_key3 索引进行 Sort-Union 合并。


SELECT * FROM products WHERE price < 100 OR category_id = 5; -- price 和 category_id 都有索引

联合索引替代索引合并 :在可能的情况下,使用联合索引可替代索引合并,提高查询效率。例如查询 single_table 表中 key1 = ‘a’ AND key3 = ‘b’ 的记录,可通过创建联合索引 idx_key1_key3(key1, key3) 来直接使用联合索引查询,避免索引合并操作。

  1. range:索引范围扫描
  • 原理: 使用索引进行范围查询 (BETWEEN, >, <, IN, OR 等)。

  • 机制: 索引有序性,定位范围起止,扫描范围内的索引记录。可处理复杂范围条件。

  • 应用场景: 查询价格范围内的商品;查询时间段内的订单;IN 列表查询。

  • 性能: 比全表扫描高效,但范围越大,效率越低。

  • 示例:


SELECT * FROM products WHERE price BETWEEN 50 AND 100;

SELECT * FROM orders WHERE order_date >= '2023-01-01' AND order_date < '2023-02-01';

范围区间确定 :对于复杂搜索条件,需分析哪些条件可使用同一索引,并确定该索引对应的范围区间。如多个条件通过 AND 连接,取各条件范围区间的交集;通过 OR 连接则取并集。若部分条件无法使用索引,则在确定范围区间时将其替换为 TRUE。

  1. index:索引全扫描
  • 原理: 扫描整个索引树,但只需要索引中的列数据。

  • 机制: 遍历索引树。索引通常比数据表小且有序,index 比全表扫描快。常发生在 “覆盖索引” 情况。

  • 应用场景: 统计记录数 (索引包含所有行);查询只需要索引列数据。

  • 性能: 比全表扫描快,但仍需扫描整个索引,低于 range

  • 示例:

定义 :当查询列表中的列全部包含在某个二级索引中,且查询条件仅涉及该索引列时,可直接遍历二级索引记录获取结果,无需回表操作。因二级索引记录较小,且避免了回表开销,查询效率较高。


SELECT COUNT(*) FROM orders; -- 若优化器选择索引扫描

SELECT order_id FROM orders; -- order_id 是主键或有索引

  1. ALL:全表扫描
  • 原理: 无法使用索引,扫描所有记录。

  • 机制: 逐行读取,检查是否满足条件。效率最低。

  • 应用场景: 表很小;查询条件无法使用索引 (无索引,或索引失效)。

  • 性能: 极低,尤其对于大表,应避免。

  • 示例:


SELECT * FROM products WHERE description LIKE '%keyword%'; -- description 无索引或前导模糊匹配

四、 注意事项

  • 二级索引+回表: 一般,查询只能用单个二级索引。优化器选扫描行数少的二级索引查询,再回表获取完整记录,根据剩余条件过滤。例如:SELECT * FROM single_table WHERE key1 = 'abc' AND key2 > 1000;,可能先用idx_key1定位key1 = 'abc',再回表根据key2 > 1000过滤。

五、 总结与优化建议

  • 索引是关键: 高效访问方法多依赖索引。合理创建和使用索引是核心。

  • 避免全表扫描: ALL 通常是性能瓶颈。尽量优化查询,使用索引。

  • 使用 EXPLAIN 分析 SQL 执行计划,看 MySQL 选择的访问方法,判断是否高效,及如何优化。

  • 关注索引类型和选择性: 不同索引 (B-tree, Hash, Fulltext) 适用不同场景。索引选择性 (区分度) 越高越好。

  • 优化 SQL: 编写高效 SQL,避免索引失效 (如索引列上用函数)。

六、 电商网站数据存储应用示例

  • const 用户登录,根据用户名 (唯一索引) 和密码 (通常不直接索引,但用户名唯一索引可快速定位)。

  • eq_ref 订单详情,订单表关联订单项表,通过订单 ID (订单项表外键,订单表主键)。

  • ref 商品分类,根据分类 ID (非唯一索引) 查询商品。

  • range 商品价格筛选,查询价格范围内的商品。

  • fulltext: 商品搜索功能。

  • index / ALL (需优化避免): 报表统计,若设计不当可能全表扫描或索引全扫描,需索引优化和查询改写。

七、 数据备份与恢复模型 (补充)

数据备份与恢复虽非直接访问方法,但保证数据安全和可用性,间接提升访问效率。

  • 备份策略:

  • 逻辑备份 (Logical Backup): 导出 SQL (如 mysqldump),灵活但慢。

  • 物理备份 (Physical Backup): 复制数据文件 (如 MySQL Enterprise Backup, Xtrabackup),快但灵活性低。

  • 全量备份 (Full Backup): 备份所有数据。

  • 增量备份 (Incremental Backup): 备份上次全量/增量备份后变化的数据。

  • 差异备份 (Differential Backup): 备份上次全量备份后变化的数据。

  • 恢复策略:

  • 完全恢复: 恢复到备份时间点。

  • 时间点恢复 (with Binary Logs): 结合备份和二进制日志,恢复到任意时间点。

  • 备份模型选择: 根据数据重要性、RTO、RPO、存储空间等选择。核心业务数据库通常采用物理全量 + 增量 + 二进制日志。

总结: 数据备份与恢复保证数据安全和可用性,是数据库稳定运行的基础。定期备份和恢复演练是 DBA 的重要职责。


http://www.niftyadmin.cn/n/5864651.html

相关文章

Python安全之反序列化——pickle/cPickle

一&#xff0e; 概述 Python中有两个模块可以实现对象的序列化&#xff0c;pickle和cPickle&#xff0c;区别在于cPickle是用C语言实现的&#xff0c;pickle是用纯python语言实现的&#xff0c;用法类似&#xff0c;cPickle的读写效率高一些。使用时一般先尝试导入cPickle&…

基于AT89C52单片机的出租车计价器

点击链接获取Keil源码与Project Backups仿真图&#xff1a; https://download.csdn.net/download/qq_64505944/90419909?spm1001.2014.3001.5501 C17 部分参考设计如下&#xff1a; 摘要 随着城市交通行业的迅速发展&#xff0c;出租车作为最主要的城市公共交通工具之一…

http 协议在互联网中扮演着怎样的角色?

互联网各领域资料分享专区(不定期更新): Sheet 正文 HTTP(超文本传输协议)在互联网中扮演着核心通信协议的角色,是万维网(World Wide Web)的基础技术之一。 1. 客户端-服务器交互的桥梁 浏览器与服务器的通信语言:HTTP定义了浏览器(客户端)如何向服务器请求资源(如…

Python 基本语法的详细解释

目录 &#xff08;1&#xff09;注释 &#xff08;2&#xff09;缩进 &#xff08;3&#xff09;变量和数据类型 变量定义 数据类型 &#xff08;4&#xff09;输入和输出 输出&#xff1a;print() 函数 输入&#xff1a;input() 函数 &#xff08;1&#xff09;注释 注…

黑马点评 面试话术

MybatisPlus session技术会把jsessionid自动写到cookie里 ThreadLocal保证线程安全 用springmvc的自定义拦截器把登出用户 查看详情 获取当前用户并且返回 上传操作 登录查看详情 以下是不拦截的路径 在tomcat负载均衡时 如果不使用redis 直接用相互拷贝 1 浪费空间 2 如果此时…

软件需求管理办法,软件开发管理指南(Word原件)

1. 目的 2. 适用范围 3. 参考文件 4. 术语和缩写 5. 需求获取的方式 5.1. 与用户交谈向用户提问题 5.1.1. 访谈重点注意事项 5.1.2. 访谈指南 5.2. 参观用户的工作流程 5.3. 向用户群体发调查问卷 5.4. 已有软件系统调研 5.5. 资料收集 5.6. 原型系统调研 5.6.1. …

JAVA-Exploit编写(13-15)--JAVAFX-GUI检测工具编写实现

目录 一,JAVAFX-GUI单个漏洞检测编写 1.1 绑定事件 1.2 Thinkphp5_Rce编写 1.3 编写利用类 1.4 Thinkphp2x_Rce编写 1.5 单个漏洞检测GUI工具完整代码 二,JAVAFX-GUI单个漏洞批量检测编写 2.1 编写利用反射类 2.2 批量检测漏洞完整GUI工具代码 三,JAVAFX-GUI…

Redis过期数据处理

Redis缓存过期后数据还能恢复吗&#xff1f; Redis缓存过期后&#xff0c;数据通常会被删除&#xff0c;但可以通过以下几种方法尝试恢复数据&#xff1a; 1. 数据备份恢复 RDB 持久化恢复&#xff1a;Redis 提供了 RDB&#xff08;Redis Database Backup&#xff09;持久化…