MySQL:索引

一、索引的常见模型

索引的出现是为了提高数据查询的效率。实现索引的方式有很多种,比较常见的数据结构有:哈希表、有序数组和搜索树。

索引是在存储引擎层实现的,不同存储引擎索引工作方式不同。

1.1 哈希表

哈希表:键值存储的数据结构,输入待查找的key,找到对应的value。通过一个哈希函数把key换算成一个确定的位置,然后把value放在数组的位置。

优点:适用于等值查询的场景,增加新的记录速度会很快。

缺点:由于不是有序的,区间查询速度很慢。

1.2 有序数组

数组按索引字段的递增顺序保存。适用于静态存储引擎,不会再修改的数据。

优点:等值查询和区间查询可以用二分查找快速查到对应数据。

缺点:插入数据就必须挪动后面所有的数据。

1.3 N叉树

为了在查询中尽量少读磁盘,访问尽量少的数据块,需要使用N叉树,而不是二叉树。这里的N取决于数据块的大小。

广泛应用于数据库引擎中。每一个索引在InnoDB中对应一棵B+树。

二、InnoDB索引模型

在InnoDB中,表都是根据主键顺序以索引的形式存放的,这种存储方式的表成为索引组织表。

InnoDB使用B+树索引模型,所以数据都是存在B+树中的。每一个索引在InnoDB中对应一棵B+树。

假设我们有一个主键列为ID的表T,表中有个字段k,并且k上有索引。(ID,K)值分别为(100,1)、(200,2)、(300,3)、(500,5)和(600,6)。两个索引对应的B+树如下:

主键索引的叶子节点存的是整行数据。在InnoDB里,主键索引也被称为聚簇索引

非主键索引的叶子节点存的是主键的值。在InnoDB里,非主键索引也被称为二级索引

  • 如果语句是select * from T where ID=500,即主键查询方式,则只需要搜索ID这棵B+树。
  • 如果语句是select * from T where k=5,即普通索引查询方式,则需要先搜索k索引树,得到ID值,再到ID索引树搜索一次,这个过程称为回表

三、索引维护、自增主键

B+树为了维护索引的有序性,在插入新值需要做必要的维护。以上图为里,若插入新的行ID为700,则只需要在R5的记录后面插入一个新的记录。若新插入的ID值为400,就要挪动后面的数据空出位置(在底层的数据页)。更糟的情况是,如果R5所在的数据页满了,根据B+树算法,这是会需要申请一个新的数据页,然后挪动部分数据过去,这个过程称为页分裂

InnoDB聚簇索引的节点也是以页为单位的,默认大小为16k,可以通过参数调整。在聚簇索引的叶子节点中,其存放的是数据。如果一个数据页存满了,MySQL 就会去申请一个新的数据页来存储数据。

  • 如果主键为自增 id ,MySQL 在写满一个数据页的时候,直接申请另一个新数据页接着写就可以了。
  • 如果主键是非自增 id,为了确保索引有序,
    • 要写入记录的目标页可能已经写入到磁盘而不只是存在于内存中,又或者目标页还没有被加载到内存中,InnoDB 在插入前需要先找到并从磁盘中读取目标页到内存中去,这会产生大量的磁盘随机 IO。
    • 因为写入是乱序的,InnoDB 需要频繁地做页分裂操作,一遍为新的行分配空间。页分裂需要移动大量数据。
    • 有序频繁的页分裂,页会变得稀疏并被不规则地填充,所以最终数据会有碎片。

除了考虑性能外,还可以从存储空间的角度来看。若表中有一个唯一字段,比如字符串类型的身份证号,那么该用自增字段做主键,还是身份证号做主键?

由于每个非主键索引的叶子节点都是主键的值,如果用身份证号(20字节)做主键,那么每个非主键索引叶子节点的占用空间远远大于主整型字段做主键。因此,主键长度越小,普通索引的叶子节点就越小,普通索引占用的空间就越小。

有没有什么场景适用于业务字段直接做主键?
只有一个索引,该索引是唯一索引(没有非聚簇索引

四、覆盖索引

若对上图的表T执行 select * from T where k between 3 and 5。会先去非聚簇索引K的B+树中找到对应的ID值,再回到主键索引搜索记录,这个回到主键索引树搜索的过程称为回表。

若执行的语句是 select ID from T where k between 3 and 5。这时只需要查ID,而ID的值以及在K的非聚簇索引的叶子节点上,不需要回表了。也就是说,在这个查询里面,索引K已经覆盖了我们的查询请求,我们称为覆盖索引

需要注意的是,在引擎内部使用覆盖索引在索引K上其实扫描三个记录,分别是叶子节点3,5,6三个记录。由于6不符合条件,所以返回给Server层只有2条记录,因此MySQL认为扫描行是2。

五、最左前缀

定义:

-- 在进行条件匹配时,必须从一个索引的最左边的列开始,并且不能跳过中间的列
-- 具体举例如下:(之前建立的索引中列的顺序,name、status、address)-- 1. 以name 作为条件进行查询,符合该法则,走索引
explain select * from tb_seller where name="小米科技";
-- 2. 以name, status 作为条件进行查询,符合该法则,走索引
explain select * from tb_seller where name="小米科技" and status="1";
-- 3. 以name, address 作为条件进行查询,不符合该法则(跳过了status),但是会走索引,仅以name为索引
explain select * from tb_seller where name="小米科技" and address="北京";
-- 4. 以status, name 作为条件进行查询,符合该法则(没有跳过某列),走索引
explain select * from tb_seller where status="1" and name="小米科技";
-- 5. 以 status,address 作为条件进行查询,不符合该法则(跳过了name),不走索引,最左侧都不存在
explain select * from tb_seller where status="1" and address="北京";-- 走索引,但是只走name, status。不会走address,因为address 在索引中位于范围查询列status的右边
explain select * from tb_seller where name='小米科技' and status > '1' and address='北京';
-- 索引结构为name,status,address。而范围查询位于address,因此应该是使用了三个索引字段。原因是MySQL 优化器会对其进行优化,所以在SQL 语句中范围查询的位置不是很重要,而范围查询的字段才是关键。当然按索引顺序写会减少优化器的开销。
explain select * from tb_seller where name='小米科技' and  address > '北京' and status = '1';

我们以(name,age)这个联合索引来分析。

索引项时按照索引定义里面出现的字段顺序排序的。当逻辑要求查找到所有名字为“张三”的人时,可以快速定位到ID4,然后遍历得到所有需要的结果。

如果要查找的是所有名字第一个字是“张”的人,也能用上这个所以,查找到第一个符合条件的记录时ID3,然后向后遍历知道不满足条件为止。

只要满足最左前缀,就可以利用索引来加速检索。这个最左前缀可以使联合索引的最左N个字段,也可以是字符串索引的最左M个字符。

建立联合索引时,如何安排索引内的字段顺序?评估标准是索引的复用能力。

第一原则是如果通过调整顺序,可以少维护一个索引,那么往往这个顺序就是优先考虑的。

六、索引下推

最左前缀可以用于在索引中定位记录。那些不符合最左前缀的部分会怎么样?

以联合索引(name,age)为例。如果现在有一个需求:检索出表中名字第一个字是张,而且年龄是10岁的所有男孩:

select * from tuser where name like ‘张%’ and age = 10 and ismale = 1;

首先根据“张%”在索引树找到第一个满足条件的记录ID3,然后判断其他条件是否满足:

在MySQL5.6之前,只能从ID3开始一个个回表,到主键索引找出数据行(这个过程InnoDB不会去看age的值),再对比字段值。

而MySQL5.6引入索引下推优化,在索引遍历过程中,对索引中包含的字段(age)先做判断,直接过滤掉不满足条件的记录,减少回表次数。

七、索引失效

1、全值匹配 :对索引中所有列都指定具体值,联合索引(name,status,address)。

explain select * from tb_seller where name='小米科技' and status='1' and address='北京市'\G;

2、最左前缀法则:如果索引了多列,要遵守最左前缀法则。指的是查询从索引的最左前列开始,并且不跳过索引中的列。

3、联合索引中范围查询右边的列,不能使用索引 。如下查询在联合索引树走到了status>1的结点之后开始遍历。使用了前两个字段的索引,第三个字段只能遍历查找。

-- 走索引,但是只走name, status。不会走address,因为address 在索引中位于范围查询列status的右边
explain select * from tb_seller where name='小米科技' and status > '1' and address='北京';
-- 索引结构为name,status,address。而范围查询位于address,因此应该是使用了三个索引字段。原因是MySQL 优化器会对其进行优化,所以在SQL 语句中范围查询的位置不是很重要,而范围查询的字段才是关键。当然按索引顺序写会减少优化器的开销。
explain select * from tb_seller where name='小米科技' and  address > '北京' and status = '1';

4、不要在索引列上进行运算操作, 否则索引将失效。

5、字符串不加单引号,造成索引失效。在查询时,没有对字符串加单引号,MySQL的查询优化器,会自动的进行类型转换,造成索引失效。

6、尽量使用覆盖索引(只访问索引的查询(索引列完全包含查询列)),减少select * 。

explain的extra字段:

  • using index :使用覆盖索引的时候就会出现
  • using where:在查找使用索引的情况下,需要回表去查询所需的数据
  • using index condition:查找使用了索引,但是需要回表查询数据
  • using index ; using where:查找使用了索引,但是需要的数据都在索引列中能找到,所以不需要回表查询数据

7、用or分割开的条件, 如果or前的条件中的列有索引,而后面的列中没有索引,那么涉及的索引都不会被用到。

8、以%开头的Like模糊查询,索引失效。如果仅仅是尾部模糊匹配,索引不会失效。如果是头部模糊匹配,索引失效。覆盖索引可以解决此问题。

9、如果MySQL评估使用索引比全表更慢,则不使用索引。

10、is NULL , is NOT NULL 有时索引失效。和9类似。

11、in 走索引, not in 索引失效。

12、单列索引和复合索引。尽量使用复合索引,而少使用单列索引 。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/142806.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

【MySQL】MySQL的索引

目录 索引1.1 概念1.2 作用1.3 使用场景1.4 使用1.5 索引最常用的数据结构 索引 1.1 概念 索引是一种特殊的文件,包含着对数据表里所有记录的引用指针。可以对表中的一列或多列创建索引, 并指定索引的类型,各类索引有各自的数据结构实现。 …

MySQL 的索引

文章目录 索引简介普通索引主键索引唯一索引全文索引外键索引复合索引复合索引生效的几种方式复合索引会失效的情况 索引的优点高性能的索引策略独立的列前缀索引和索引的选择性复合索引选择合适的索引列顺序聚簇索引索引的 Btree 结构聚簇索引和非聚簇索引的区别聚簇索引的优点…

什么是 MySQL 索引?

什么是索引? 假设我们有一张数据表 employee(员工表),该表有三个字段(列),分别是name、age 和address。假设表employee有上万行数据(这公司还真大),现在需要从这个表中查找出所有名字是‘ZhangSan’的雇员信…

MySql知识体系总结(2021版)

存储引擎负责在MySQL中存储数据、提取数据、开启一个事务等等。存储引擎通过API与上层进行通信,这些API屏蔽了不同存储引擎之间的差异,使得这些差异对上层查询过程透明。存储引擎不会去解析SQL。 二、对比InnoDB与MyISAM 1、 存储结构 MyISAM&#xff…

一文搞懂MySQL索引所有知识点(建议收藏)

Mysql索引 索引介绍 索引是什么 官方介绍索引是帮助MySQL高效获取数据的数据结构。更通俗的说,数据库索引好比是一本书前面的目录,能加快数据库的查询速度。 一般来说索引本身也很大,不可能全部存储在内存中,因此索引往往是存储…

Doris安装

Apache Doris 由百度大数据部研发(之前叫百度 Palo,2018 年贡献到 Apache 社区后, 更名为 Doris ),在百度内部,有超过 200 个产品线在使用,部署机器超过 1000 台,单一 业务最大可达…

深入理解hashmap底层实现原理

目录 总体介绍 HashMap元素的存储 在hashmap中添加元素 HashMap的扩容机制 HashMap的线程安全性 1.添加和删除元素时存在不安全性 2.进行扩容操作时存在不安全性 3.哈希冲突存在不安全性 4.线程之间的不可见性导致安全问题 总体介绍 HashMap是我们用于元素映射使用频率最…

RK3588平台开发系列讲解(项目篇)YOLOv5部署测试

平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、YOLOv5环境安装二、YOLOv5简单使用2.1、获取预训练权重文2.2、YOLOv5简单测试2.3、转换为rknn模型2.4、部署到 RK 板卡三、airockchip/yolov5简单测试3.1、转换成rknn模型并部署到板卡沉淀、分享、成长,让自己和他…

HTML编码问题导致的乱码

今天一个学弟问了一个问题&#xff0c;它写的HTML代码打开显示的是乱码。 然后就给我发来了代码。 就一个HTML文件和一个文件夹&#xff0c;打开一看&#xff0c;很简单的代码。 <!DOCTYPE html> <html lang""> <head><meta charset"UTF…

URL和HTML编码

URL和HTML编码 在呈现HTML页面时,有时候需要显示一些特殊的字符,例如”<”和”&”,因为它们是HTML专用字符,因此需要一些技巧.例如要想显示AT&T,在代码中必须写成AT&amp;T。同样URL中的,&,/等字符也为专用字符,所以如果需要在URL参数中使用它们,也必须对这些…

简单的Html编码转换工具

一、前言 因为项目经常会碰Html转码&#xff0c;特别是返回的xml报文&#xff0c;总是显示&# 十六进制的编码&#xff0c;查中文的时候特别不方便&#xff0c;所以就做了一个简单的C#桌面应用程序。 二、涉及软件 Visual Studio 2019 Preview 三、使用框架 .NET Fram…

怎么设置html代码中的编码格式,html怎么设置编码

在html中&#xff0c;可以使用meta标签来设置编码&#xff0c;语法格式“”。meta标签提供了HTML文档的元数据&#xff0c;元数据不会显示在客户端&#xff0c;但是会被浏览器解析&#xff1b;而charset属性用于定义文档的字符编码。 本教程操作环境&#xff1a;windows7系统、…

Unicode编码对应的HTML 、JS 、CSS码

平时写代码很少用到HTML的特殊字符&#xff0c;最常用的可能是 了&#xff0c;但有时在移动端为了节省时间&#xff0c;可能会用这些字符实现某种特殊效果&#xff0c;现整理如下&#xff1a; 使用方法&#xff1a; 这些字符属于unicode字符集&#xff0c;所以&#xff0c;你…

HTML之编码规范

HTML之编码规范 img 标签要写 alt 属性单标签不要写闭合标签自定义属性要以 data-开头td 要在 tr 里面&#xff0c;li 要在 ul/ol 里面ul/ol 的直接子元素只能是 lisection 里面要有标题标签使用 section 标签增强 SEO行内元素里面不可使用块级元素每个页面要写要用 table 布局…

【HTML 教程】HTML 字符编码

作者 | 阮一峰 简介 网页包含了大量的文字&#xff0c;浏览器必须知道这些文字的编码方法&#xff0c;才能把文字还原出来。 一般情况下&#xff0c;服务器向浏览器发送 HTML 网页文件时&#xff0c;会通过 HTTP 头信息&#xff0c;声明网页的编码方式。 Content-Type: text/ht…

HTML编码规范

本篇文章是基于王叨叨大佬师父维护的文档梳理的&#xff0c;有兴趣可以去看一下原文HTML编码规范。 1. 缩进与换行 【建议】 使用 2 个空格作为一个缩进层级&#xff0c;不允许使用tab字符 解释&#xff1a; ​ 具体项目&#xff0c;可以使用2个空格&#xff0c;也可以使用…

HTML 编码(字符集)总结,你了解了多少

Web 浏览器必须知道要使用哪个字符集&#xff0c;才能正确显示 HTML 页面。 文章目录 Web 浏览器必须知道要使用哪个字符集&#xff0c;才能正确显示 HTML 页面。前言一、HTML charset 属性二、字符集之间的差异ASCII 字符集ANSI 字符集 (Windows-1252)ISO-8859-1 字符集UTF-8 …

【HTML基础笔记】之【常用编码】

HTML 常用编码 4.1 HTML 实体编码 HTML实体编码&#xff0c;也即HTML中的转义字符。 在 HTML 中&#xff0c;某些字符是预留的&#xff0c;例如在 HTML 中不能使用小于号<和大于号>&#xff0c;这是因为浏览器会误认为它们是标签。如果希望正确地显示预留字符&#xf…

CTR预估之DNN系列模型:FNN/PNN/DeepCrossing

前言 在上一篇文章中 CTR预估之FMs系列模型:FM/FFM/FwFM/FEFM&#xff0c;介绍了FMs系列模型的发展过程&#xff0c;开启了CTR预估系列篇章的学习。FMs模型是由线性项和二阶交互特征组成&#xff0c;虽然有自动学习二阶特征组合的能力&#xff0c;一定程度上避免了人工组合特征…

SQL SERVER DATEPART函数

定义&#xff1a; DATEPART函数返回指定日期的指定部分。 语法&#xff1a; DATEPART(datepart,date) 参数&#xff1a; ①datepart 参数可以是下列的值&#xff1a; datepart缩写年(Year)YEAR, YY, YYYY季度(Quarter)Q, QQ, QUARTER月(Month)M, MM, MONTH年中的日(Day of year…