MySql优化-索引命中

本文介绍如何使用MySql的Explain命令分析SQL查询效率,包括查询类型的解释、访问类型的意义及其对性能的影响,以及如何识别并处理无效索引。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在项目开发中SQL是必不可少的,表索也一样.这些SQL的运行性能不知道吗?有多少是命中了索引的?命中哪个索引?索引中有哪个是无效索引?这些无效索引是否会影响系统的性能?带着这些问题我们一起来学习一下.
  MySql中是通过 Explain 命令来分析低效SQL的执行计划。命令的使用很简单.
示例 explain select * from adminlog
执行结果:
id  select_type table   partitjons  type    possible_keys   key key_len ref row filtered    Extra
1   SIMPLE  adminlog        ALL                 2   100  
执行结果每一列的说明:

1、 select_type : 查询类型,常见的值[SIMPLE:简单表,不使用表连接或子查询。PRIMARY : 主查询,外层的查询。UNION 第二个或者后面的查询语句。SUBQUERY : 子查询中的第一个select]
2、table :输出结果的表
3type : 表示MySql在表中找到所需行的方式,或者叫访问类型。常见的类型:
ALL index   range   ref eq_ref  const,system    NULL
从左到右,性能由最差到最好。
  3.1 type=ALL 全表扫描,
  3.2 typeindex 索引全扫描,遍历整个索引来查询匹配的行
  3.3 type=range 索引范围扫描,常见于 <,<=,>,>=,between,in等操作符。
  例 
    explain select * from adminlog where id>0 , 
    explain select * from adminlog where id>0 and id<=100
    explain select * from adminlog where id in (1,2) 

  3.4 type=ref 使用非唯一索引或唯一索引的前缀扫描,返回匹配某个单独值的记录行。ref还经常出现在JOIN操作中

  3.5 type=eq_ref 类似于ref,区别就在使用的索引是唯一索引,对于每个索引键值,表中有一条记录匹配;简单来说,说是多表连接中使用 主建或唯一健作为关联条件
  3.6 type=const/system 单表中最多有一个匹配行。主要用于比较primary key [主键索引]或者unique[唯一]索引,因为数据都是唯一的,所以性能最优。条件使用=。 
  3.7 type=NULL 不用访问表或者索引,直接就能够得到结果 
例 explain select 1 from dual,类型type 还有其他值 如ref_or_null : 与ref 类似,区别在于条件中包含对NULL的查询.   index_merge : 索引合并优化, unique_subquery : in的后面是一个主键字段的子查询。index_subquery : 与                             unique_subquery 类似,区别在于in的后面是查询非唯一索引字段的子查询
4、possible_keys : 可能使用的索引列表.
5、key : 实现执行使用索引列表
6、key_len : 索引的长度
7、ref : 显示使用哪个列或常数与key一起从表中选择行。
8、row : 执行查询的行数,简单且重要,数值越大越不好,说明没有用好索引
9、filtered:
10、Extra: 该列包含MySQL解决查询的详细信息。
  10.1 Not exists  
  10.2 range checked for each record
    没有找到合适的索引
  10.5 using index 只使用索引树中的信息而不需要进一步搜索读取实际的行来检索表中的信息。就是建议取索引列。这样就可以不要通过索引去实际表中找数据了。直接返回索引列的数据。一次查询。否则就是索引表查一次,实际表中查一次。
  10.6 using temporary
为了解决查询,MySQL需要创建一个临时表来容纳结果。典型情况如查询包含可以按不同情况列出列的GROUP BYORDER BY子句时。

无效索引: 数据变化不大的列。如XX类型,是否有效,项目ID等列的索引都是无效的。这些无效索引还是影响Insert 、Update、Delete 语句的性能。因为这些语包的执行都要对索引表进行更新。又因为这些表的值变化不大,数据库很难为他们合理分配索引。所以影响语句的性能。

IN,OR 是否会走索引:
一条SQL会不会走索引一个看条件使用的运算符,另一个看有没有索引。所以SQL会不会走索引和IN.OR,group by 没有关系。
什么运算符不走索引,<>,!=
OR 有个点要注意一下:就OR前后两个条件都要有索引整个SQL才会使用索引。只要有一个条件没索引那么整个SQL都不使用索引。
如果出现OR的一个条件没有索引时,建议使用 union 
例:
explain SELECT * FROM cbdfinance.adminlog where id = 1 
union SELECT * FROM cbdfinance.adminlog where OriginalData='UpdateModelErrorMsg';

结果:

1   PRIMARY adminlog        const   PRIMARY PRIMARY 4   const   1   100.00   
2   UNION   adminlog        ALL                 11  10.00   Using where
    UNION RESULT    <union1,2>      ALL                         Using temporary
使用OR第二个条件没有索引:
explain SELECT * FROM cbdfinance.adminlog where id = 1 or OriginalData='UpdateModelErrorMsg';
结果:
1   SIMPLE  adminlog        ALL PRIMARY             11  18.18   Using where
explain SELECT * FROM cbdfinance.adminlog where id = 1 or id=2;
explain SELECT * FROM cbdfinance.adminlog where id = 1 or SearchText1='UpdateModelErrorMsg';
explain SELECT * FROM cbdfinance.adminlog where id in (1,2)
explain SELECT * FROM cbdfinance.adminlog group by SearchText1
<think>好的,我现在需要解释MySQL中的“索引命中”、“索引回表”和“索引下推”这三个概念。首先,我得确保自己正确理解每个术语的含义,然后组织语言用中文清晰地表达出来,同时遵循用户提供的格式要求,比如内公式用$...$,独立公式用$$...$$,并且结构要清晰。 首先,索引命中。这应该是指当执查询时,MySQL能够利用索引来快速定位数据,而无需全表扫描。比如,如果有一个索引在name字段上,查询条件WHERE name = 'Alice'就会命中这个索引。需要说明索引的结构,比如B+树,以及如何通过索引快速查找数据。 接下来是索引回表。当查询的列不在索引中时,即使命中索引MySQL还需要根据索引中的主键值回到主键索引(聚簇索引)中查找完整的数据。这个过程称为回表。例如,索引是(name),但查询需要获取age,这时候就需要回表。这里可能需要提到覆盖索引的概念,即如果索引包含所有需要的字段,就可以避免回表。 然后是索引下推(Index Condition Pushdown,ICP)。这是在MySQL 5.6引入的优化技术,允许在存储引擎层提前过滤不符合条件的,减少回表次数。比如,查询条件WHERE name LIKE 'A%' AND age > 20,如果索引在(name, age)上,在没有ICP的情况下,存储引擎会先找到所有name以A开头的主键,然后回表获取age再过滤。而有了ICP,存储引擎会直接在索引中检查age条件,减少回表的数据量。需要解释ICP的作用和如何提升性能。 接下来需要考虑如何将这些内容结构化,分点说明,每个部分可能还需要例子或场景说明。同时注意用户提到的格式要求,内数学表达式比如索引结构可能需要用LaTeX,例如B+树的高度$h$,查找复杂度$O(\log n)$等。不过根据用户给的例子,可能不需要太复杂的公式,所以这里可能需要酌情处理。 需要检查是否有遗漏的关键点,比如索引的结构、回表的原因、覆盖索引、ICP的工作原理和版本支持。同时确保语言通俗易懂,避免技术术语堆砌,但又要准确。可能还需要对比有无ICP的情况下的执流程差异,以突出其优化效果。 最后,确保回答符合用户的结构要求:分点解释每个概念,可能包括定义、原理、示例、影响或优化建议。同时使用中文,避免Markdown格式,但保持段落清晰,可能用序号或标题来分隔各个部分。同时注意LaTeX的正确使用,比如内公式用$...$,独立公式如果需要的话用$$...$$,但根据用户的问题,可能不需要太多公式,主要是在解释索引结构或查询过程时可能需要。 总结一下,回答的结构大致如下: 1. 索引命中 - 定义:查询条件使用索引快速定位数据 - 原理:B+树结构,减少扫描- 示例:WHERE子句使用索引- 注意点:最左前缀原则,索引选择性 2. 索引回表 - 定义:需要回主键索引取数据 - 原理:二级索引存储主键值 - 示例:查询列不在索引- 优化:覆盖索引 3. 索引下推 - 定义:存储引擎层提前过滤 - 原理:在索引遍历时应用WHERE条件 - 示例:组合索引,部分条件在索引中处理 - 优势:减少回表次数,提升性能 在写作过程中,需要检查每个部分是否准确,是否有错误。例如,索引下推是否仅适用于组合索引,还是单列索引也可以?实际上,ICP适用于索引能够覆盖的列,不管是否是组合索引,但通常组合索引更能体现其优势。另外,需要确认MySQL版本支持情况,ICP从5.6开始支持。 可能还需要提到执计划中的Using index condition来表示ICP的使用,而Using index表示覆盖索引。这些细节能帮助用户更好地理解如何诊断和优化查询。 最后,确保语言流畅,逻辑清晰,符合用户的要求,分点讲解,帮助用户逐步理解这三个概念。</think>### MySQL索引命中索引回表、索引下推详解 #### 一、索引命中 1. **定义** 当查询条件**完全或部分匹配索引结构**时,MySQL可通过索引快速定位数据,避免全表扫描。例如: ```sql SELECT * FROM users WHERE name = 'Alice'; -- 若name字段有索引,则命中 ``` 2. **原理** - 索引通常采用$B^+$树结构,树高$h$决定查询复杂度为$O(\log n)$。 - **最左前缀原则**:联合索引$(a, b, c)$只能按$a$ → $a+b$ → $a+b+c$的顺序使用。 - **索引选择性**:唯一性高的字段(如ID)更适合建索引。 3. **示例** - 命中:`WHERE a=1 AND b=2`(联合索引$(a,b)$) -命中:`WHERE b=2`(未从最左字段$a$开始) --- #### 二、索引回表 1. **定义** 当索引**未覆盖查询所需全部列**时,需根据索引中的主键值**回主键索引(聚簇索引)**获取完整数据。 2. **原理** - 二级索引(如`INDEX(name)`)仅存储主键值。 - 若查询需获取`age`字段(未包含在索引中),流程如下: ```sql 1. 通过二级索引找到name='Alice'对应的主键id=100 2. 回主键索引查找id=100的,获取age=25 ``` 3. **优化:覆盖索引** 将查询列全部加入索引,例如: ```sql CREATE INDEX idx_name_age ON users(name, age); SELECT age FROM users WHERE name = 'Alice'; -- 无需回表 ``` --- #### 三、索引下推(ICP,Index Condition Pushdown) 1. **定义** MySQL 5.6+引入的优化技术,**将WHERE条件过滤提前到存储引擎层执**,减少回表次数。 2. **原理** - **无ICP**:存储引擎仅按索引最左前缀筛选数据,剩余条件由Server层处理。 - **有ICP**:存储引擎直接利用索引中的字段过滤数据,减少传递给Server层的数据量。 3. **示例** ```sql -- 表结构:INDEX(name, age) SELECT * FROM users WHERE name LIKE 'A%' AND age > 20; ``` - **无ICP**:先找到所有`name LIKE 'A%'`的主键,回表后由Server层过滤`age > 20`。 - **有ICP**:存储引擎在索引中直接过滤`name LIKE 'A%' AND age > 20`,仅回表符合条件的主键。 4. **优势** - 减少回表次数,降低I/O开销。 -计划显示`Using index condition`即表示触发ICP。 --- ### 总结对比 | 概念 | 触发场景 | 优化目标 | 关键标志 | |------------|------------------------------|-------------------|-----------------------| | 索引命中 | 查询条件匹配索引结构 | 减少扫描数 | `Using index` | | 索引回表 | 查询列未完全被索引覆盖 | 避免回表 | 无 | | 索引下推 | WHERE条件可被索引部分覆盖 | 减少回表次数 | `Using index condition` | 通过合理设计索引(如覆盖索引、联合索引)和利用ICP,可显著提升查询性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值