说说对mysql索引的理解

本文深入探讨了MySQL的存储引擎,如MyISAM和InnoDB的区别,重点介绍了索引的概念,包括聚集索引和非聚集索引的工作原理。文章强调了索引创建的策略,指出索引并非越多越好,分析了何时创建索引以及如何利用explain分析SQL执行计划。同时,列举了可能导致索引失效的各种情况,如OR操作、函数使用、LIKE模糊匹配等。最后,提到了覆盖索引的概念及其对查询性能的提升作用。

mysql索引的理解

概述

       我们在使用MySQL的时候最经常能想到的优化方案可能就是加索引了吧,在表数据量很大的时候,添加索引可以帮我们极大的提升数据查询效率,那么索引是什么?你对MySQL的索引真的了解吗?

1、MySQL存储引擎

提到索引的类型就要先提到MySQL的存储引擎了,我们经常用到的会是myisam和innodb了,那么他们有什么区别呢,我们打开MySQL在磁盘上的存储文件会发现myisam是由表结构文件*.frm,数据文件*.myd和索引文件*.myi三部分组成的,
他的数据文件和索引文件是分开的,也就是我们说的非聚集索引,而innodb是只有表结构文件*.frm和数据文件*.idb组成,他的数据和索引是存储在一起的,也就是聚集索引;还有就是myisam不支持事务,
而innodb支持事务,myisam只支持表锁,innodb支持表锁和行锁(默认),因此在实际使用中如果是读取的操作比较多,可是使用myisam,其他大多数场景都是使用的innodb了,目前mysql默认的也都是innodb存储引擎了。

2、索引是什么

        聚集索引也就是数据和文件是存储在一起的,在数据文件中直接存储的就是根据索引字段排好序的B+tree结构的数据,我们如果是根据主键查询的话直接就可以快速的定位到B+tree中主键字段对应的叶子节点然后获取数据,如果是非主键索引的话就要先找到非主键字段的叶子节点(非主键的叶子节点并没有储存数据),然后再链接到主键的节点从而找到数据,效率相对于主键查找要慢一点,因为聚集索引的数据是按照索引排好序存储的,因此使用的时候必须要有主键或者唯一约束,如果没有的话,系统会帮我们创建一个默认的rowNum作为唯一约束来存储数据;再来说说非聚集索引吧,
非聚集索引就是数据和索引是分开储存的,索引中b+tree的叶子节点并没有存储数据,而是存的地址引用,具体的数据是在另外一个数据文件中存储的,查询数据时根据索引查询到叶子节点中的地址,然后再根据地址从数据文件中查询到对应的数据返回,与聚集索引相比,因为数据是分开存储的,因此就不需要一定要有主键或者唯一约束了,对于主键或者是其他索引字段,在定位到叶子节点后通过地址直接就可以查到数据了,查询数据的效率是一样的。

3、什么时候创建索引

       我们创建索引的时候,一般会有单一索引和复合索引,其实单一索引也可以算作是只有一个字段的复合索引,正如大家都知道的那样,我们创建索引都会针对于经常使用的查询条件、排序、分组字段进行创建,索引也不是越多越好, 对于使用比较少的字段就没必要创建了,每个索引都需要在文件中增加一个数据结构,不仅会占用磁盘空间,在对数据添加删除修改时还需要去维护索引,都是有成本的。索引还有个非常重要的原则就是最左前缀原则,例如有A,B,C三个字段
我们创建复合索引(A,B,C),那么在使用的时候,如果是where A=‘1’ and B=‘2’ and C='3’来使用时完全可以用到索引的,但如果是where A=‘1’ and C=‘3’ 那么就只会用到字段A这一部分索引了,那要如果是where B=‘2’ and C=‘3’ 那么索引就会失效了,造成全表扫描。其实索引失效还有很多种情况的,我们接下来分析。

4、索引使用情况分析

通常是用explain来分析sql的执行计划的:在这里插入图片描述

  1. id:表示需要查询序列号,如果存在子查询的话就会有递增的多个,id越大的会越先执行,如果id相同的 话按照从上到下的顺序执行

  2. select_type:表示查询类型:

    • SIMPLE:表示简单的查询,
    • PRIMARY:如果包含子查询的话,外层的查询就会被标识为PRIMARY,
    • UNION:联合查询后面的SELECT语句,
    • DEPENDENT UNION:和union类似,都是存在于子查询中,如果联合查询是存在于子查询中,查询的结果会影响外层的结果时,会出现DEPENDENT UNION
    • union result :union联合查询的结果,包含素有被union的所有查询结果
    • SUBQUERY:子查询中的第一个select 语句
    • DERIVED 派生表的子查询,from 后面子句中的子查询
  3. table:显示查询的表名,也有可能是查询结果的简称

  4. type:这个是最重要的一列结果了,显示的是对表的访问方式

    • ALL:全表扫描,是最差的结果了
    • index:扫描整个索引树,在建立了复合索引,并且查询条件没有使用到索引,查询结果中只包含索引字段的时候会使用index,比ALL的全表扫描要好一点
    • range :在使用索引查询一定范围的数据的时候,会使用range
    • ref :作为查询条件的索引列的值是一个常量的时候,查询效率是比较高了
    • eq_ref : 和ref类似,区别在于eq_ref是关联的字段是唯一索引列或者主键,最多会有一条结果返回,算是使用索引最好的结果了
    • const:作为查询条件的列是唯一索引或者是主键的时候,因为只会返回一条结果,mysql优化器就能将该查询转换为常量,效率是非常快的
    • system:system是const的一种,被查询的表只有一条记录满足的时候就会是system了,例如把包含const的查询的结果作为表进行查询

    5、索引失效的情况

    结合mysql索引的结构,我们就会发现它就是一个帮我们吧数据排好序的树状结构,我们正常使用的时候就会按照排好序去取数据,是很快的,但是如果下面几种情况就会破坏索引的规则了,也就是索引会失效
    在这里插入图片描述

    • 在查询条件中使用or,根据索引的储存结构就会发现,如果是or的前后都是索引字段的话,是可以使用索引的,否则就会索引失效,全表扫描了
    • 在索引列上使用函数计算,在数据的储存结构中是按照索引字段的值作为B+tree的节点的,如果进行计算的话,就不是索引结构中的储存的值了,自然也就失效了,还有一种情况就是索引字段值得类型不匹配,会导致查询的时候
    • mysql做隐式的转换,也是会失效的
    • 使用like,在使用like的时候,如果是%在后面的话,是可以在索引树匹配到部分数据的,可以使用到索引,如果是%在前面,那么就会索引失效了
    • 还有就是我们有种说法是使用is null,is not null 或者!=null的情况会索引失效,其实这种说法是不正确的
    • 最后再说一下覆盖索引,覆盖索引就是需要查询的结果可以直接从索引结构的叶子节点上取到,不需要再通过主键索引二次查找了,如果我们查询的结果字段刚好是查询条件的索引字段的话,就会用到覆盖索引,查询效率是非常高的,因此返回结果尽量少写*,使用覆盖索引。
<think>好的,我现在需要回答用户关于MySQL索引的问题。首先,用户之前询问了深度学习的内容,现在转向数据库索引,可能是在学习技术栈的不同部分。我需要确保回答的结构清晰,覆盖主要知识点,并且符合用户提到的格式要求。 首先,我应该回忆一下MySQL索引的基本概念,然后分门别类地整理知识点。常见的索引类型有B+树索引、哈希索引、全文索引等。接下来是索引的数据结构,比如B+树的结构特点,为什么MySQL使用B+树而不是B树或者其他结构。然后要考虑索引的类型,比如主键索引、唯一索引、普通索引、联合索引等,每种索引区别和应用场景。 另外,需要包括索引的创建和管理,比如创建索引的语法,如何选择索引的列,索引的优化策略,比如最左前缀原则,覆盖索引索引下推这些概念。还有索引的优缺点,比如提高查询速度但会增加写入开销,占用存储空间等。 还要考虑索引的使用注意事项,比如什么时候应该创建索引,什么时候不应该,如何通过EXPLAIN来分析索引的使用情况,索引的失效场景,比如使用函数、类型转换、OR条件等导致索引失效的情况。 可能还需要提到聚簇索引和非聚簇索引区别,InnoDB和MyISAM在索引实现上的不同。此外,索引的存储引擎支持情况,比如MEMORY引擎支持哈希索引,InnoDB的自适应哈希索引等。 有没有遗漏的部分?比如索引的维护,比如重建索引索引的统计信息,Cardinality的概念,以及索引的选择性和查询效率的关系。此外,还有全文索引的特殊处理,比如自然语言模式和布尔模式,以及5.6版本后InnoDB对全文索引的支持。 还有,需要确保使用正确的LaTeX格式,比如数学表达式和公式用$或$$包裹,结构分点明确。需要检查是否有错误的技术细节,比如B+树的高度计算,或者联合索引的最左匹配原则的具体例子。 可能还需要举例说明,比如创建索引SQL语句,如何查看索引信息,使用EXPLAIN的结果解读。但用户可能只需要知识点的罗列,不需要具体例子,但适当举例有助于理解。 最后,总结部分可以提到索引的最佳实践,比如避免过多索引,定期分析索引使用情况,根据查询模式设计索引等。同时,确保内容准确,比如InnoDB的聚簇索引结构,行数据存储的位置,以及二级索引的访问需要两次查找等。 现在需要将这些内容组织成一个结构化的回答,分点说明,使用适当的子标题,确保每个部分清晰,并且符合用户之前设定的格式要求,比如使用中文,正确的LaTeX语法,独立公式用$$包裹,行内公式用$包裹,避免使用Markdown格式。</think>以下是MySQL索引的核心知识点整理: ### 1. 索引基础原理 - **B+树结构**:主流索引类型,满足$O(\log n)$查询复杂度 $$ \text{节点容量}=16KB/(主键大小+指针大小) $$ 例:8B主键+6B指针 → 约1170子节点/层 - **页分裂机制**:当插入数据导致页使用率超过$\frac{15}{16}$时触发 - **聚簇索引**:InnoDB主键索引,数据与索引存储在一起(非主键时自动创建隐藏RowID) ### 2. 索引类型体系 | 类型 | 数据结构 | 支持引擎 | 特点 | |------|----------|----------|------| | 主键索引 | B+Tree | InnoDB | 唯一且非空,叶节点含完整数据 | | 唯一索引 | B+Tree | 所有引擎 | 强制列值唯一性 | | 普通索引 | B+Tree | 主要引擎 | 允许重复值,叶节点存主键 | | 全文索引 | 倒排索引 | InnoDB(5.6+) | 支持`MATCH AGAINST`查询 | | 空间索引 | R-Tree | MyISAM | 处理GIS数据,支持`MBRContains`等函数 | ### 3. 复合索引规则 - **最左前缀原则**: 索引`(a,b,c)`有效查询: ```sql WHERE a=1 AND b>2 WHERE c=3 AND b=5 AND a=2 -- 优化器自动调整顺序 ``` 无效场景: ```sql WHERE b=1 -- 跳过首列 WHERE a=1 AND c=3 -- 中间断层 ``` - **索引跳跃扫描**:MySQL 8.0新特性,即使未指定首列也可使用索引(需低基数首列) ### 4. 性能优化要点 - **覆盖索引**:查询字段全部包含在索引中,避免回表 ```sql -- 使用索引(a,b) SELECT b FROM table WHERE a=5 ``` - **索引下推(ICP)**:5.6+版本,WHERE条件在存储引擎层过滤 ```sql /* 索引(a,b), 查询条件a=1 AND b LIKE 'test%' */ 旧方案:回表后过滤b条件 ICP:在索引层直接过滤b条件 ``` - **索引选择率**:最优索引应满足 $$ \frac{\text{distinct值数量}}{\text{总行数}} \geq 10\% $$ ### 5. 索引失效场景 1. **隐式类型转换**: ```sql WHERE varchar_col = 123 -- 转换为字符串比较 ``` 2. **函数操作**: ```sql WHERE YEAR(create_time)=2023 -- 改为范围查询 ``` 3. **前导通配符**: ```sql WHERE name LIKE '%abc' -- 无法使用索引 ``` 4. **OR条件**: ```sql WHERE a=1 OR b=2 -- 除非a,b都有独立索引 ``` ### 6. 索引管理命令 ```sql -- 查看索引信息 SHOW INDEX FROM tbl; -- Cardinality统计 ANALYZE TABLE tbl; -- 强制使用索引 SELECT * FROM tbl USE INDEX(idx_name); -- 索引重建(消除碎片) ALTER TABLE tbl ENGINE=InnoDB; ``` ### 7. 设计实践准则 - **三星索引原则**: 1. WHERE条件列形成索引左前缀(★) 2. ORDER BY列包含在索引中(★) 3. 覆盖所有SELECT字段(★) - **空间占用计算**: 每GB数据约需额外100-300MB索引空间 - **写入代价**:每个索引增加约10%-20%的INSERT/UPDATE耗时 最新版本改进(MySQL 8.0): - 新增`INVISIBLE INDEX`功能,可暂时禁用索引测试影响 - 支持降序索引`(a DESC, b ASC)`,优化ORDER BY ... DESC查询 - 引入函数索引`INDEX((DATE(create_time)))`,突破字段操作限制
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值