mysql数据库索引详解,索引优化、分析
1.什么是索引
索引在MySQL中是比较常见的,索引就相当于我们看书的目录,它是帮助MySQL高效获取数据的一种数据结构,主要用来提高数据的检索效率,减少IO成本,同时通过索引对数据进行排序,降低排序成本。
2.索引的作用
加快查询速度:通过索引快速定位数据。
保证数据唯一性:如主键和唯一索引。
优化排序和分组:索引可以加速
ORDER BY和GROUP BY操作。
3.索引的分类
- 按「数据结构」分类:B+tree索引、Hash索引、Full-text索引。
- 按「物理存储」分类:聚簇索引(主键索引)、二级索引(辅助索引)。
- 按「字段特性」分类:主键索引、唯一索引、普通索引、前缀索引。
- 按「字段个数」分类:单列索引、联合索引。
聚簇索引主要是指数据和索引放到一块,B+树叶子节点报存了整行数据。
非聚簇索引是数据与索引分开的,B+树叶子节点只保存主键值。
4.索引的结构
在创建表时,InnoDB 存储引擎会根据不同的场景选择不同的列作为索引:
- 如果有主键,默认会使用主键作为聚簇索引的索引键(key);
- 如果没有主键,就选择第一个不包含 NULL 值的唯一列作为聚簇索引的索引键(key);
- 在上面两个都没有的情况下,InnoDB 将自动生成一个隐式自增 id 列作为聚簇索引的索引键(key);
其它索引都属于辅助索引(Secondary Index),也被称为二级索引或非聚簇索引。创建的主键索引和二级索引默 认使用的是 B+Tree 索引。
数据库的索引和数据都是存储在硬盘的,我们可以把读取一个节点当作一次磁盘I/O操作。
重点:B+Tree存储千万级的数据只需要3-4层高度就可以满足,意味着从千万级别的表查询目标数据最多需要3-4次磁盘的I/O,所以B+Tree相对于B树和二叉树来说,最大优势在于查询效率很高,因为即使数据量很大,磁盘I/O仍维持在3-4次。
5.主键索引的B+Tree和二级索引的B+Tree的区别
1)主键索引的 B+Tree 的叶子节点存放的是实际数据,所有完整的用户记录都存放在主键索引的 B+Tree 的叶子节点里;
2) 二级索引的 B+Tree 的叶子节点存放的是主键值,而不是实际数据。
6.什么是回表查询
用二级索引查数据时,会先检二级索引中的 B+Tree 的索引值(商品编码,product_no),找到对应的叶子节点,然后获取主键值,然后再通过主键索引中的 B+Tree 树查询到对应的叶子节点,然后获取整行数据。这个过程叫「回表」,也就是说要查两个 B+Tree 才能查到数据。
不过,当查询的数据是能在二级索引的 B+Tree 的叶子节点里查询到,这时就不用再查主键索引查,比如下面这条查询语句:
select id from product where product_no = '0002';
这种在二级索引的 B+Tree 就能查询到结果的过程就叫作「覆盖索引」,也就是只需要查一个 B+Tree 就能找到数据。
7.为什么MySQL 默认的存储引擎 InnoDB 采用的是 B+ 作为索引的数据结构,而不是B树
原因有:
- B+ 树的非叶子节点不存放实际的记录数据,仅存放索引,因此数据量相同的情况下,相比于既存索引又存记录的 B 树,B+树的非叶子节点可以存放更多的索引,因此 B+ 树可以比 B 树更「矮胖」,查询底层节点的磁盘 I/O次数会更少。
- B+ 树有大量的冗余节点(所有非叶子节点都是冗余索引),这些冗余索引让 B+ 树在插入、删除的效率都更高,比如删除根节点的时候,不会像 B 树那样会发生复杂的树的变化;
- (范围查询)B+ 树叶子节点之间用链表连接了起来,有利于范围查询,而 B 树要实现范围查询,因此只能通过树的遍历来完成范围查询,这会涉及多个节点的磁盘 I/O 操作,范围查询效率不如 B+ 树。
8.索引为什么会失效的六种情况
今天给大家介绍了 6 种会发生索引失效的情况:
1)当我们使用左或者左右模糊匹配的时候,也就是 like %xx 或者 like %xx% 这两种方式都会造成索引失效;
原因:因为索引 B+ 树是按照「索引值」有序排列存储的,只能根据前缀进行比较,而%在左边模糊匹配时无法识别左边是对于哪个值。
2)当我们在查询条件中对索引列使用函数,就会导致索引失效。
原因:因为索引保存的是索引字段的原始值,而不是经过函数计算后的值,自然就没办法走索引了。
3)当我们在查询条件中对索引列进行表达式计算,也是无法走索引的。
原因:因为索引保存的是索引字段的原始值,而不是经过表达式计算后的值,自然就没办法走索引了。
4)MySQL 在遇到字符串和数字比较的时候,会自动把字符串转为数字,然后再进行比较。如果字符串是索引列,而条件语句中的输入参数是数字的话,那么索引列会发生隐式类型转换,由于隐式类型转换是通过 CAST 函数实现的,等同于对索引列使用了函数,所以就会导致索引失效。
5)联合索引要能正确使用需要遵循最左匹配原则,也就是按照最左优先的方式进行索引的匹配,否则就会导致索引失效。
原因:在联合索引的情况下,数据是按照索引第一列排序,第一列数据相同时才会按照第二列排序。
也就是说,如果我们想使用联合索引中尽可能多的列,查询条件中的各个列必须是联合索引中从最左边开始连续的列。如果我们仅仅按照第二列搜索,肯定无法走索引。
6)在 WHERE 子句中,如果在 OR 前的条件列是索引列,而在 OR 后的条件列不是索引列,那么索引会失效。
原因:这是因为 OR 的含义就是两个只要满足一个即可,因此只有一个条件列是索引列是没有意义的,只要有条件列不是索引列,就会进行全表扫描。
9.索引优化的方法
1)前缀索引优化
前缀索引顾名思义就是使用某个字段中字符串的前几个字符建立索引,那我们为什么需要使用前缀来建立索引呢? 使用前缀索引是为了减小索引字段大小,可以增加一个索引页中存储的索引值,有效提高索引的查询速度。在一些大字符串的字段作为索引时,使用前缀索引可以帮助我们减小索引项的大小。
不过,前缀索引有一定的局限性,例如:
1.order by 就无法使用前缀索引;
2.无法把前缀索引用作覆盖索引;
2)覆盖索引优化
覆盖索引是指 SQL 中 query 的所有字段,在索引 B+Tree 的叶子节点上都能找得到的那些索引,从二级索引中查询得到记录,而不需要通过聚簇索引查询获得,可以避免回表的操作。
假设我们只需要查询商品的名称、价格,有什么方式可以避免回表呢?
我们可以建立一个联合索引,即「商品ID、名称、价格」作为一个联合索引。如果索引中存在这些数据,查询将不会再次检索主键索引,从而避免回表。
所以,使用覆盖索引的好处就是,不需要查询出包含整行记录的所有信息,也就减少了大量的 I/O 操作。
3)主键索引最好是递增的
InnoDB 创建主键索引默认为聚簇索引,数据被存放在了 B+Tree 的叶子节点上。
也就是说,同一个叶子节点内的各个数据是按主键顺序存放的,因此,每当有一条新的数据插入时,数据库会根据主键将其插入到对应的叶子节点中。
如果我们使用自增主键,那么每次插入的新数据就会按顺序添加到当前索引节点的位置,不需要移动已有的数据,当页面写满,就会自动开辟一个新页面。因为每次插入一条新记录,都是追加操作,不需要重新移动数据,因此这种插入数据的方法效率非常高。
如果我们使用非自增主键,由于每次插入主键的索引值都是随机的,因此每次插入新的数据时,就可能会插入到现有数据页中间的某个位置,这将不得不移动其它数据来满足新数据的插入,甚至需要从一个页面复制数据到另外一个页面,我们通常将这种情况称为页分裂。页分裂还有可能会造成大量的内存碎片,导致索引结构不紧凑,从而影响查询效率。
4)索引最好设置为 NOT NULL
为了更好的利用索引,索引列要设置为 NOT NULL 约束。有两个原因:
第一原因:索引列存在 NULL 就会导致优化器在做索引选择的时候更加复杂,更加难以优化,因为可为 NULL 的列会使索引、索引统计和值比较都更复杂,比如进行索引统计时,count 会省略值为NULL 的行。
第二个原因:NULL 值是一个没意义的值,但是它会占用物理空间,所以会带来的存储空间的问题,因为 InnoDB 存储记录的时候,如果表中存在允许为 NULL 的字段,那么行格式 (opens new window)中至少会用 1 字节空间存储 NULL 值列表,如下图的紫色部分:
10.索引的最左前缀匹配原则(联合索引)
MYSQL索引的最左前缀匹配原则是指在使用联合索引时,查询条件必须从索引的最左侧开始匹配。
只有第一个索引匹配成功了才会用第二个索引匹配,以此类推。
1)索引下推:是一种减少回表查询的,提高查询效率的技术,即将部分数据下推到引擎层进行过滤,减少从表中读取的数据行。
MYSQL5.6版本以后有个索引下推的优化。
例如有联合索引(a,b,c)然后有一条查询语句:
select * from user where a = 1,c = 3;
在MYSQL5.6版本之前,在根据索引a = 1过滤完数据后,就会回到server层进行回表查询
而MYSQL5.6版本之后,有了索引下推功能,在根据索引a = 1过滤完数据后,会将c=3下推到给存储引擎层进行过滤,利用c=3过滤掉不符合的数据,然后再返回给server层,大大增加了查询效率。
2)跳过扫描范围访问(Skip Scan Range Access Method)
在MYSQL 8.0.13引入了Skip Scan Range Access Method,在一定条件下,利用范围查询替代了全表扫描的发生。
例如有联合索引(a,b)然后有一条查询语句:
select * from user where b = 3;
在MYSQL 8.0.13前,就会进行全表扫描。
在MYSQL 8.0.13后,由于引入了Skip Scan Range Access Method,当索引最左字段a的基数很小时(比如只有a = 1和a = 2的情况),会将a = 1和a = 2 分别拼接到查询条件中(即where条件后)从而实现,最左匹配原则。
3)面试题:假如你有一个查询很慢,且你已经确定查询使用了一个复合索引,你会如何诊断并优化这个查询?
答:首先,可以使用EXPLAIN语句来查看查询的执行计划,确认是否使用了正确的的索引。如果发现查询没有充分利用索引,可以查询是否存在违犯最左匹配原则的情况,调整查询条件的顺序,以及其他优化措施,如:减少返回的列数,使用索引覆盖,前缀索引优化等。
4)EXPLAIN语句
EXPLAIN语句用于分析 SELECT 语句的执行计划,帮助开发者了解查询是如何执行的,可以查看Mysql如何执行查询,包括哪些索引被使用、查询的执行顺序、扫描的行数等等。
EXPLAIN SELECT * FROM users WHERE age > 30;

5)SQL语句执行很慢,如何分析的呢?
采用MySQL自带的分析工具Explain,加在查询语句前即可。
1)执行命令后查看key和key_len检查是否命中索引。
2)通过type字段检查sql是否能进一步优化,是否出现all(全表扫描)和index(全索引扫描)
3)通过extra判断是否出现了回表情况(using index condition)
5)在mysql中如何查看sql执行时间?
在MySQL中,profiling功能可以帮助你分析SQL查询的性能。默认情况下,profiling是关闭的,你需要通过以下命令将其开启:
1.SET profiling = 1;
2.执行要查看时间的sql :select * from user;
3.如何调用:SHOW PROFILES; 查看执行时间。
文章参考 http://www.dgyongsheng88.cn/news/30642330.html
mysql数据库索引详解,索引优化、分析的更多相关文章
- 如何查看mysql数据库的引擎/MySQL数据库引擎详解
一般情况下,mysql会默认提供多种存储引擎,你可以通过下面的查看: 看你的mysql现在已提供什么存储引擎:mysql> show engines; 看你的mysql当前默认的存储引擎:mys ...
- MySQL数据库备份详解
原文:MySQL数据库备份详解 对于任何数据库来说,备份都是非常重要的 数据库复制不能取代备份的作用 比如我们由于误操作,在主数据库上删除了一些数据,由于主从复制的时间很短,在发现时,从数据库上的数据 ...
- Mysql索引详解及优化(key和index区别)
MySQL索引的概念 索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针.更通俗的说,数据库索引好比是一本书前面的目录,能加快数据库 ...
- MySQL数据库基础详解(非原创)
文章大纲 一.数据库简介二.Mysql数据库简介三.Mysql安装与服务启动(Windows版本)四.Mysql图形化工具五.Mysql存储引擎精讲六.Mysql数据类型介绍七.Mysql主要专业名称 ...
- mysql数据库参数详解
1.配置参数 MySQL有两种途径途径了解其的配置参数,一个是MySQL交互模式下的命令SHOW VARIABLES,一个使用mysqladmin variables 查询. MySQL的配置参数分 ...
- MySQL数据库引擎详解
作为Java程序员,MySQL数据库大家平时应该都没少使用吧,对MySQL数据库的引擎应该也有所了解,这篇文章就让我详细的说说MySQL数据库的Innodb和MyIASM两种引擎以及其索引结构.也来巩 ...
- mysql distinct 用法详解及优化
本事例实验用表task,结构如下 MySQL> desc task; +-------------+------------+------+-----+-------------------+- ...
- (7) MySQL数据库备份详解
对于任何数据库来说,备份都是非常重要的 数据库复制不能取代备份的作用 比如我们由于误操作,在主数据库上删除了一些数据,由于主从复制的时间很短,在发现时,从数据库上的数据可能也已经被删除了, 我们不能使 ...
- Jmeter(七) - 从入门到精通 - 建立数据库测试计划实战<MySQL数据库>(详解教程)
1.简介 在实际工作中,我们经常会听到数据库的性能和稳定性等等,这些有时候也需要测试工程师去评估和测试,上一篇文章宏哥主要介绍了jmeter连接和创建数据库测试计划的过程,宏哥在文中通过示例和代码非常 ...
- MySQL数据库事务详解
微信公众号[程序员江湖] 作者黄小斜,斜杠青年,某985硕士,阿里 Java 研发工程师,于 2018 年秋招拿到 BAT 头条.网易.滴滴等 8 个大厂 offer,目前致力于分享这几年的学习经验. ...
随机推荐
- helm Error: INSTALLATION FAILED: cannot re-use a name that is still in use
前言 使用helm安装服务报错,修改chat后重新安装报错:安装失败:无法重复使用仍在使用的名称 解决方法 1.查找安装失败的服务 helm -n {namespace} ls -a 2.删除安装失败 ...
- JVM堆内存(heap)详解
JAVA堆内存管理是影响性能主要因素之一.堆内存溢出是JAVA项目非常常见的故障,在解决该问题之前,必须先了解下JAVA堆内存是怎么工作的.先看下JAVA堆内存是如何划分的,如图:Java堆内存又溢出 ...
- oracle中的aix,Oracle在AIX上一些处理
一.Oracle在aix上连接 1.su - oracle //进入oracle用户: 2.export ORACLE_SID=house //指定实例,多个实例的情况下: 3.sqlplus / ...
- 【Docker】本地镜像发布到阿里云
本地镜像发布到阿里云 本地镜像发布到阿里云流程 镜像的生成方法 1. 前面的DockerFile 2. 从容器创建一个新的镜像 docker commit [OPTIONS] 容器ID [REPOSI ...
- Debian 下安装 Nginx
Debian 下安装 Nginx 非常容易. apt update apt install nginx 输入以下命令查看是否可以正常访问, 顺便验证下安装是否成功. curl -I 127.0.0.1 ...
- 离线版nrfutil工具安装方法
简介 nrfutil是Nordic提供的命令行工具集.支持以下功能: 基于Jlink的固件烧录.读取.flash擦除.recover 基于MCUBOOT的固件升级(DFU) 基于nRF5 bootlo ...
- 【开源推荐】AI Interviewer:基于Spring-Alibaba-AI的智能面试官系统(附GitHub实战教程)
项目背景 作为开发者,你是否经历过: 技术面试时因紧张发挥失常? 刷了1000+LeetCode却不会表达解题思路? 花费上千元购买模拟面试服务? 今天推荐的AI Interviewer开源项目,正是 ...
- cesium裁切面实践
cesium裁切面实践:沙盒地址 (打不开的自行科学访问) 裁切面法线方向指向保留的部分,本案例通过法线配合unionClippingRegions参数实现相比官方案例没有的:多裁切面互裁,裁两边留中 ...
- JavaScript 没有“包”
前言 除了古老的 C/C++,几乎所有的编程语言都有模块系统,都有官方的包管理器.我们一般不自己实现所有的代码,实际应用开发过程中大量使用开源库和框架.这篇文章演示了如何把自己实现的库变成一个包,一个 ...
- 【经验】博客|Windows下,一键安装和部署 hexo-admin 插件(Hexo 静态博客)
1. 在博客根目录下运行下列指令 npm install --save hexo-admin -y echo "hexo clean && hexo g -d"&g ...