二十、MySQL技术体系之InnoDB存储引擎的索引

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 二十、MySQL技术体系之InnoDB存储引擎的索引

一、什么是索引?

1、对数据库表中一列或多列的值进行排序的一种数据存储结构。
2、类似书的目录,使用索引可以快速访问数据库表中的行记录数据。
3、基本原理:存储引擎通过遍历索引定位基表中的行,然后返回给Server层,再去为这些行记录数据进行where条件过滤。
4、InnoDB存储引擎的叶子结点数据是按照主键rowid进行排序的,目的是方便对磁盘做顺序I/O

二、索引的数据结构

MySQL数据库使用B+tree索引结构,B+tree是由二叉树 -> 平衡二叉树 -> B-tree树逐步演化而成。

1、二叉树结构

每个结点至多有2个子结点
二叉树有左右序之分,次序不能颠倒
二叉树中,左子树的键值永远比右子树的键值小,并且小于根结点的键值

2、平衡二叉树结构

- 解决了二叉树节点深度增加,查询的均分复杂度上升的问题,拥有比二叉树更快的查询速度
- 条件:
   左右两个子树的高度差的绝对值不超过1
   左右两个子树也都是平衡二叉树

3、B-tree结构(Btree、B树)

一个结点可以拥有多于2个子结点的多叉查找树
所有叶子结点都在同一层
叶子结点不包含任何关键字信息

4、B+tree索引结构

B-tree结构的变体,双向链表结构,一种多路搜索树
所有关键字信息都存放在叶子结点,并包含这些关键字记录的指针
叶子结点按照关键字大小顺序连接,因此访问关键字的顺序是连续性的,不需要回溯上一个结点
所有数据都存放在叶子结点中

三、B+tree索引分类

show index from 表名,
  可以查看表中有哪些索引,使用expalin命令可以查看SQL语句的执行计划(优化器对SQL语句的优化执行方案)。

1、聚集索引和普通索引

  • B+tree索引分为两大类:聚集索引和非聚集索引

聚集索引

叶子结点存放表中所有行数据记录的信息;
    对于聚集索引,数据即索引,索引即数据;
    创建主键时会自动创建;

普通索引

叶子结点不包含所有行的数据记录,只存放索引字段的键值和行记录数据的主键值;
    检索数据时,通过普通索引叶子结点找到主键,再通过主键来获取行数据记录;

MySQL语法:

ALTER TABLE 表名 ADD INDEX 索引名(列名);
      CREATE INDEX 索引名 ON 表名(列名);
create index ename_index on emp(ename);
drop index ename_index on emp;
show index on emp;

2、主键索引(聚集索引)和唯一索引

主键索引必须满足三个条件:

主键索引就是聚集索引

   主键值必须唯一;

   不能包含NULL值;

   必须保证值是自增的(自增保证insert是顺序的,基于磁盘的顺序访问特性,提高了存取效率);

  • 唯一索引必须满足一个条件:

     值必须是唯一的,但是值允许是NULL;

  • 一张表只能有一个主键索引,但是唯一索引可以有多个
  • MySQL语法:

   创建主键索引:创建主键时自动创建;

   创建唯一索引:ALTER TABLE emp add unique(列名);

3、覆盖索引

  • 通过索引就可以直接返回查询数据,不需要在查询索引之后再去回表查询数据,减少了磁盘I/O操作,因此查询速度快
  • 使用explain命令查看SQL语句的执行计划
    extra列出现Using index关键字,表明SQL语句使用了覆盖索引;
  • 符合覆盖索引的场景
    必须在select列出所需要的列,而不能写select * from emp;

4、前缀索引

  • BLOB、TEXT、较长的VARCHAR类型的列,为前面最左侧的若干个字符创建的一种索引
  • MySQL语法:
    ALTER TABLE emp add key(columnName(prefixLength));
  • 这种索引很小,所查询较快
  • 不足之处:

   不能在ORDER BY和GROUP BY中使用;

   不能用做覆盖索引

5、联合索引(复合索引)

  • 在表中两个或者两个以上的列上创建的索引
  • 利用索引上的附加列,可以缩小检索的段池范围,更快的检索数据
  • MySQL语法:
    create index idx_c1_c2 epm(列名c1,列名c2);
  • 在使用过程中,必须要满足最左前缀原则:

   创建索引时,将选择性高的列放在前面;

   一条查询语句可以只使用索引中的一部分,但是必须从最左索引列开始;

   如使用索引idx_c1_c2,可以检索c1或者c1,c2,但是不能直接检索c2;

  • 例外情况select * from emp where c1=? or c2=?

   不能使用联合索引,需要创建两个单列索引或者考虑使用union;

6、哈希索引

  • 采用哈希算法,把键值换算成哈希值
  • 只能进行等值查询,不能进行排序、模糊查找、范围查询
  • 查询速度快,检索时不需要像B+tree从根节点到叶子结点逐级查找,只需一次哈希算法即可立刻定位到数据位置

四、使用explain命令查看SQL语句的执行计划

1、type列,表示查询类型

  • 出现all关键字,说明全表扫描

2、key列,表示是否使用索引

  • 出现null关键字,说明没有使用索引

3、rows列,表示在SQL语句执行过程中扫描行数的估算值

  • 数值越大,说明需要扫描的行数越多,耗时越长

4、extra列,

  • 出现Using filesort关键字,说明排序使用了文件系统,性能较差
  • 出现Using temporary关键字,说明使用了内存临时表空间,性能较差
  • 出现Using index condition关键字,说明使用了索引过滤(ICP优化),where条件可以使用索引,在存储引擎层直接做过滤操作
  • 出现Using MRR关键字,说明范围扫描使用了MRR优化特性,

     把普通索引的叶子结点上查找到的主键值的集合存储到read_rnd_buffer;

     在read_rnd_buffer中对主键值排序;

     最后利用排序后的主键值集合进行顺序回表读取行记录数据;

     因此达到了进行顺序I/0访问磁盘的目标,避免查询过程中出现I/0随机访问,提高了I/O效率;

  • 出现Using join buffer(Batched Key Access)关键字,说明表连接使用BKA优化特性,

     BKA是提高join性能的算法,在读取被join表的记录时使用顺序I/0;

     当MySQL使用索引访问第二个join表时,使用一个join buffer收集第一个操作对象生成的相关列值,批量传递给引擎层做索引查找;

     使用时基于MRR特性;

5、filtered列,表示返回结果的行占需要读取到的行(rows列的值)的百分比

五、索引的利弊

1、使用索引的好处

  • 提高数据检索效率
  • 提高聚合函数的效率 (组函数 max(), min()...)
  • 提高排序效率
  • 使用覆盖索引可以避免回表

2、使用索引的正确方式

  • 适合创建索引的列:

   经常被查询的条件列;

   经常用于表连接的列;

   经常排序分组的列;

  • 不适合创建索引的列:

   选择性低的字段不要创建索引,如性别字段只能筛选出1/2的数据,区分度不大,不该创建索引;

   很少查询的列不要创建索引,需要事先和需求方沟通确认;

   大数据类型字段不要创建索引,如text、blob类型字段不要创建索引;

  • 避免的情况

   尽量避免不要使用NULL,MySQL对含有NULL值的列很难进行查询优化,会让索引、索引的统计信息及比较运算更加复杂,因此DBA经常推荐使用NOT NULL;

   尽量在MySQL客户端的应用程序中做运算和判断,不要让数据库做各种运算;

3、索引失效的情况

  • 通过索引扫描的行记录数超过全表的30%,优化器不会走索引,变成全表扫描
  • 联合索引中,第一个查询条件不是最左索引列
  • 联合索引中,第一个索引列使用范围查询,只能使用到部分索引,有ICP出现
  • 联合索引中,第一个查询条件不是最左前缀列
  • 模糊查询条件列,最左以通配符%开始(可以放到子查询里)
  • 两个单列索引,一个检索,一个排序,只能使用其中一个索引(查询语句中最多只能使用一个索引),这种情况考虑创建联合索引
  • 查询字段有索引,但是使用了函数运算

4、索引的副作用

  • 创建太多的索引,在DML操作时,将会增加维护索引的负担
相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
10天前
|
SQL 关系型数据库 MySQL
深入解析MySQL的EXPLAIN:指标详解与索引优化
MySQL 中的 `EXPLAIN` 语句用于分析和优化 SQL 查询,帮助你了解查询优化器的执行计划。本文详细介绍了 `EXPLAIN` 输出的各项指标,如 `id`、`select_type`、`table`、`type`、`key` 等,并提供了如何利用这些指标优化索引结构和 SQL 语句的具体方法。通过实战案例,展示了如何通过创建合适索引和调整查询语句来提升查询性能。
89 9
|
2天前
|
存储 缓存 关系型数据库
【MySQL进阶篇】存储引擎(MySQL体系结构、InnoDB、MyISAM、Memory区别及特点、存储引擎的选择方案)
MySQL的存储引擎是其核心组件之一,负责数据的存储、索引和检索。不同的存储引擎具有不同的功能和特性,可以根据业务需求 选择合适的引擎。本文详细介绍了MySQL体系结构、InnoDB、MyISAM、Memory区别及特点、存储引擎的选择方案。
【MySQL进阶篇】存储引擎(MySQL体系结构、InnoDB、MyISAM、Memory区别及特点、存储引擎的选择方案)
|
7天前
|
存储 Oracle 关系型数据库
索引在手,查询无忧:MySQL索引简介
MySQL 是一款广泛使用的关系型数据库管理系统,在2024年5月的DB-Engines排名中得分1084,仅次于Oracle。本文介绍MySQL索引的工作原理和类型,包括B+Tree、Hash、Full-text索引,以及主键、唯一、普通索引等,帮助开发者优化查询性能。索引类似于图书馆的分类系统,能快速定位数据行,极大提高检索效率。
33 8
|
7天前
|
存储 关系型数据库 MySQL
MySQL存储引擎详述:InnoDB为何胜出?
MySQL 是最流行的开源关系型数据库之一,其存储引擎设计是其高效灵活的关键。InnoDB 作为默认存储引擎,支持事务、行级锁和外键约束,适用于高并发读写和数据完整性要求高的场景;而 MyISAM 不支持事务,适合读密集且对事务要求不高的应用。根据不同需求选择合适的存储引擎至关重要,官方推荐大多数场景使用 InnoDB。
48 7
|
12天前
|
缓存 关系型数据库 MySQL
MySQL 索引优化与慢查询优化:原理与实践
通过本文的介绍,希望您能够深入理解MySQL索引优化与慢查询优化的原理和实践方法,并在实际项目中灵活运用这些技术,提升数据库的整体性能。
44 5
|
2天前
|
存储 关系型数据库 MySQL
【MYSQL】 ——索引(B树B+树)、设计栈
索引的特点,使用场景,操作,底层结构,B树B+树,MYSQL设计栈
|
4天前
|
存储 Oracle 关系型数据库
数据库传奇:MySQL创世之父的两千金My、Maria
《数据库传奇:MySQL创世之父的两千金My、Maria》介绍了MySQL的发展历程及其分支MariaDB。MySQL由Michael Widenius等人于1994年创建,现归Oracle所有,广泛应用于阿里巴巴、腾讯等企业。2009年,Widenius因担心Oracle收购影响MySQL的开源性,创建了MariaDB,提供额外功能和改进。维基百科、Google等已逐步替换为MariaDB,以确保更好的性能和社区支持。掌握MariaDB作为备用方案,对未来发展至关重要。
18 3
|
4天前
|
安全 关系型数据库 MySQL
MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!
《MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!》介绍了MySQL中的三种关键日志:二进制日志(Binary Log)、重做日志(Redo Log)和撤销日志(Undo Log)。这些日志确保了数据库的ACID特性,即原子性、一致性、隔离性和持久性。Redo Log记录数据页的物理修改,保证事务持久性;Undo Log记录事务的逆操作,支持回滚和多版本并发控制(MVCC)。文章还详细对比了InnoDB和MyISAM存储引擎在事务支持、锁定机制、并发性等方面的差异,强调了InnoDB在高并发和事务处理中的优势。通过这些机制,MySQL能够在事务执行、崩溃和恢复过程中保持
22 3
|
4天前
|
SQL 关系型数据库 MySQL
数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog
《数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog》介绍了如何利用MySQL的二进制日志(Binlog)恢复误删除的数据。主要内容包括: 1. **启用二进制日志**:在`my.cnf`中配置`log-bin`并重启MySQL服务。 2. **查看二进制日志文件**:使用`SHOW VARIABLES LIKE 'log_%';`和`SHOW MASTER STATUS;`命令获取当前日志文件及位置。 3. **创建数据备份**:确保在恢复前已有备份,以防意外。 4. **导出二进制日志为SQL语句**:使用`mysqlbinlog`
27 2
|
17天前
|
关系型数据库 MySQL 数据库
Python处理数据库:MySQL与SQLite详解 | python小知识
本文详细介绍了如何使用Python操作MySQL和SQLite数据库,包括安装必要的库、连接数据库、执行增删改查等基本操作,适合初学者快速上手。
129 15