首页 > 数据库 >MySQL索引

MySQL索引

时间:2024-10-30 20:17:21浏览次数:8  
标签:index name age 查询 索引 字段 MySQL

索引概述

介绍

  • 索引(index)是帮助MySQL高效获取数据的数据结构(且 有序)。在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引。

优缺点

索引结构

MySQL的索引是在存储引擎层实现的,不同的存储引擎有不同的结构,主要包含以下几种:

B-Tree(多路平衡查找树)

  • 以一颗最大度数(max-degree)为5(5阶)的b-tree为例(每个节点最多存储4个key,5个指针)

往下看,我来告诉你,啥叫5阶,什么是key,指针又是什么。

下图可见:红色方框中已经有5个数值了,但这并不是最终形态,因为我们的最大度数是5,而度数指的是指针。

看下图最终形态,8是中间元素,那么此时 中间元素就会向上裂变。

为什么会向上裂变呢,因为此时我们的最大度数是5阶,也就是5个指针,4个key,key指的就是方框中的数值,当数值大于4个,或指针大于5个时,就不符合5阶B数的规则了,那么就得分裂。

指针:也叫最大度数,也叫5阶。一个指针对应这一个字节点

节点:

子节点:

key:关键字

最后来一张动态图演示一下B树的新增过程吧。

B+Tree

  • 设计的目的是为了优化磁盘读写操作。
  • 以一颗最大度数(max-degree)为5(5阶)的b+tree为例

且叶子节点形成一个单向链表、

MySQL版 B+Tree

  • MySQL索引数据结构对经典的B+Tree进行了优化。在原B+Tree的基础上,增加一个指向相邻叶子节点的链表指针,就形成了带有顺序指针的B+Tree,提高区间访问的性能。

为什么InnoDB会选择B+Tree?

  • 相对于二叉树,层级更少,搜索效率高。
  • 对于B-Tree,无论是叶子节点还是非叶子节点,都会保存数据,这样导致一页中存储的键值减少【一页的大小是16kb】,指针也跟着减少,要同样保存大量数据,只能增加树的高度,导致性能降低。
  • 相对Hash索引,B+Tree支持范围匹配及排序操作。

索引分类

在InnoDB存储引擎中,根据索引的存储形式,可以分为以下两种

聚集索引的选取规则:

  • 如果存在主键,主键索引就是聚集索引。
  • 如不存在主键,将使用第一个唯一(UNIQUE)索引作为聚集索引。
  • 如果表没有主键,或没有合适的唯一索引,则InnoDB会自动生成一个GEN_CLUST_INDEX的6字节长整型字段,作为隐藏的聚集索引。

注意事项:

  • 一个表只能有一个聚集索引,可以有多个二级索引。
  • 更新聚集索引列可能导致大量的页分裂或合并操作,从而影响性能。
  • 除了聚集索引之外的所有索引都是二级索引,它们并不决定数据行的实际存储顺序。
  • 如果查询仅需访问二级索引就能完成,则无需回查聚集索引,这种情况被称为"覆盖索引"。
  • 与直接使用聚集索引相比,使用二级索引可能效率较低,尤其是在大量随机读取的情况下。

聚集索引的查询过程

回表查询的过程

覆盖索引

什么是覆盖索引:一条select 语句在查询的过程中使用到了索引,并且需要返回的列,在该索引中已经全部能够找到。

  • 当查询仅需访问二级索引就能完成时,则无需回表查询

二级索引:idx_name_age 包含了 name  与  age两个字段

查询语句:select name,age from table where name = 'xxx'

像上述这种情况,所需要查询的字段正是二级索引中所包含的字段,二级索引可以直接满足查询需求,所以这种情况下就无需再回表查询了。

  • 需要回表查询的情况

二级索引:idx_name_age 包含了 name  与  age两个字段

查询语句:select id,name,age from table where name = 'xxx'

加了一个id,二级索引里面是不包含的,所以这里就必须查完二级索引后,在查聚集索引。

索引语法

查询索引

  • show index from table_name

删除索引

  • drop index index_name  on table_name

创建索引

  • create [ unique | fulltext ] index index_name on table_name ( index_ col_name,... )
  • unique :代表创建的是一个唯一索引,该字段不能出现重复数据。
  • fulltext:代表创建的是一个全文索引。
  • index_col_name:代表的是要创建索引的字段,如果是一个字段,代表的是单列索引;如果是多个字段,代表的是联合索引。
  • 如果不加上面这两个可选参数(unique | fulltext),代表创建的是一个常规索引。

测试数据表

案例

  • name字段为姓名字段,该字段的值可能重复,为该字段创建索引

  • phone手机号字段的值,是非空,且唯一的,为该字段创建唯一索引

  • 为profession,age,status创建联合索引

  • 为email创建一个索引来提升查询效率

索引-使用规则-验证索引效率

上两图:

  • 该表有1千万条数据
  • name字段是没有索引的
  • 可以看见,这条sql扫全表了,速度相当慢,一条数据就需要6秒的时间

好,接下来,我们给name字段加上普通索引试试看。

上三图

  • 加上索引后,速度的提升是指数级的
  • 可以看见,这条查询语句已经使用上索引了,row也为1了

最左前缀法则

  • 如果索引了多列(联合索引),要遵守最左前缀法则。最左前缀法则指的是查询从索引的最左列开始(也就是最左边的那个索引字段必须存在),并且不跳过索引中的列。
  • 如果跳跃某一列,索引将部分失效(后面的字段索引失效)

我有一张1千万数据的表,并且创建了如下图中的联合索引

看如下案例:

  • 案例一:

索引的三个字段都用上了。

  • 案例二:

将job字段的查询去除了,索引依然生效了,且索引key_len的长度也减少了。

  • 案例三:

将age字段也去除了,索引依然生效,且索引key_len的长度也减少了。

  • 案例四:

将name字段的查询去除了,发现没有走索引,扫全表了,这是因为没有遵循最左原则,name字段是该索引的最左侧字段,但查询时缺不存在。

  • 案例五:

和案例四结果一样。

  • 案例六:

我将查询的顺序给打乱了,name在SQL中并非是最左侧的字段,但为何还是触发了索引呢?

        原因:回看上面的最左前缀法则,其中说明是:最左侧的那个索引字段必须存在,而并没有顺序要求,所以在查询时,name只需要存在即可,位置想放哪放哪。

  • 案例七:

这个案例中,我将中间的索引字段age取消了,那么此时触发了索引字段跳过,从ref中可以看到,只有一个const,只触发了name一个字段的索引,job没有触发,因为失效了。

范围查询

  • 联合索引中,出现范围查询(>或<),范围查询右侧的列索引失效。
  • 案例:

如下图,当使用了范围查询时,范围查询右侧的列索引就失效了,可以看见只生效了name与age的索引字段,job索引字段没有生效

所以在我们实际开发中,如果业务允许,就使用 >= 或 <= ,这样就规避了这个失效规则。

索引失效的多种情况

如下图,这是我当前表中所有的索引,下面索引失效情况下都会使用。

  • 索引列运算:不要在索引列上进行运算操作,索引将失效。

图一:触发了age的单列索引

图二:age字段进行了 “加法”,导致索引失效了

  • 字符串类型字段使用时,不加引号,索引将失效。

图一:下面是加了引号的情况

图二:下面是没加引号的情况

  • 模糊查询

  • 如果仅仅是尾部模糊匹配,索引不会失效。如果是头部模糊匹配,索引失效。

图一:尾部模糊匹配,索引生效

图二:头部模糊匹配,索引失效

  • or连接的条件

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

图一:两个字段都有索引,所以两个索引都用上了,索引生效

图二:age有索引,但managerid没有索引,所以age的索引也失效了

  • 数据分布影响

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

图一:得知,年龄最大的为1000

图二:查询年龄大于990的数据时,用上了索引

图三:查询年龄小于1000的数据时,没有使用索引,全表查询了

SQL提示(指定索引进行查询)

  • SQL提示,是优化数据库的一个重要手段,简单来说,就是在SQL语句中加入一些人为的提示来达到优化操作的目的。

如下所有案例都是用name字段举例,name字段有两个索引,一个单列索引,一个联合索引。

  • use index:建议MySQL使用某个索引
  • explain select * from emp use index(idx_emp_name) where name = 'xxx';

图一:可以看见,可能会使用到的索引有两个,使用上的索引是联合索引。

图二:这里建议MySQL使用单列索引,MySQL采纳了

  • ignore index:不建议MySQL使用某个索引
  • explain select * from emp ignore index(idx_emp_name)  where name = 'xxx';

可以看见下图,MySQL也采纳了我的建议,不使用单列索引,所以使用了联合索引

  • force index:强制使用某个索引
  • explain select * from emp  force index(idx_emp_name) where name ='xxx';

前缀索引

  • 当字段类型为字符串(varchar , text 等)时,有时候需要索引很长的字符串,这会让索引变的很大,查询时,浪费大量的磁盘IO,影响查询效率。此时可以只将字符串的一部分前缀,建立索引,这样可以大大节约索引空间,从而提高索引效率。
  • 语法:
  • create index idx_xxxx on table_name(column(n));
  • n :代表该字段前几个字符。例如:n = 5 ,那么就是前5个字符

前缀长度

  • 可以根据索引的选择性来决定。
  • 什么是索引的选择性?选择性指的是 不重复的索引值(基数)和 数据表的记录总数的比值。
  • 索引选择性越高 则查询效率越高,唯一索引的选择性是 1,这是最好的索引选择性,性能也是最好的。

索引选择性如何得到,如下两个语句可以计算出索引选择性:

select  count (distinct  email)  / count(*)  from tb_user;


select count(distinct substring(email,1,5))  / count(*)  from tb_user;

如下图,我们来看看前缀索引他是怎样获取数据的。

上图中,1至7就不细说了,

  1. 先拿email的前5个字符在二级索引中进行查询,最终得到了主键ID为1。
  2. 然后拿到1 去聚集索引中查询,最后得到 一个完整的row,也就是一行完整的数据。
  3. 那么一行完整的数据之后,拿到这行完整数据里面的email字段的数据与where中提供的email查询数据相比较。如果完全相同,那么获取。
  4. 可以看见二级索引的叶子节点,它们是链表的形式,所以,mysql会继续查询下一个叶子节点,看看是否前缀数据相同,如果还相同,那么重复1-3操作。直至不相同。

索引设计原则

  1. 针对于数据量较大,且查询比较频繁的表建立索引。
  2. 针对于常作为查询条件(where)、排序(order by)、分组(group by)操作的字段建立索引。
  3. 尽量选择区分度高【区分度:可以理解为重复率,例如身份证号是唯一的,那么区分度就是最高的】的列作为索引,尽量建立唯一索引,区分度越高,使用索引的效率越高。
  4. 如果是字符串类型的字段,字段的长度较长,可以针对于字段的特点,建立前缀索引。
  5. 尽量使用联合索引,减少单列索引,查询时,联合索引很多时候可以覆盖索引,节省存储空间,避免回表,提高查询效率。
  6. 要控制索引的数量,索引并不是多多益善,索引越多,维护索引结构的代价也就越大,会影响赠删改的效率。
  7. 如果索引列不能存储NULL值,请在创建表时使用NOT BULL约束它,当优化器知道每列是否包含NULL值时,它可以更好地确定哪个索引最有效地用于查询。

标签:index,name,age,查询,索引,字段,MySQL
From: https://blog.csdn.net/qq_43683281/article/details/142911604

相关文章

  • MySQL存储引擎——针对实习面试
    目录MySQL支持哪些存储引擎?MySQL存储引擎架构了解嘛?MyISAM和InnoDB有什么区别?MyISAM和InnoDB如何选择?如何查看表的存储引擎?如何修改表的存储引擎?MySQL支持哪些存储引擎?MySQL支持多种存储引擎,包括InnoDB、MyISAM、MEMORY、ARCHIVE、BLACKHOLE、FEDERATED、NDBCluste......
  • Ubuntu22 mysql8 MHA高可用
    mha-manager地址:https://github.com/yoshinorim/mha4mysql-managermha-node地址:https://github.com/yoshinorim/mha4mysql-node mha有mha-manager和mha-node2个组件由于主节点有可能会被切换成从节点,而每一个从节点也有可能会被切换成主节点所以MHA对Mysql复制环境有特......
  • Mysql梳理11——聚合函数
    Mysql梳理11——聚合函数Mysql梳理11——聚合函数11.1引言11.2聚合函数介绍11.2.1什么是聚合函数11.2.2聚合函数类型11.2.3聚合函数语法11.3具体聚合函数11.3.1AVG和SUM函数11.3.2MIN和MAX函数11.3.3COUNT函数11.4GROUPBY11.4.1基本使用11.4.2使用多个列......
  • GIS空间索引技术
    地理信息系统(GeographyInformationSystem,简称GIS)的主要任务之一是有效地检索空间数据及快速响应不同用户的在线查询。地理空间索引技术和方法是GIS的关键技术。是快速高效查询、检索和显示地理空间数据的重要指标。常用的空间索引技术介绍和比较: 网格空间索引、四叉树空间索......
  • MySQL敏感数据进行加密的几种方法
    使用MySQL内置的加密函数AES_ENCRYPT和AES_DECRYPT函数方法介绍:AES(AdvancedEncryptionStandard)是一种对称加密算法。在MySQL中,可以使用AES_ENCRYPT函数对数据进行加密,使用AES_DECRYPT函数进行解密。这种加密方式的特点是加密和解密使用相同的密钥。示例:......
  • MySQL如何输出自己的AWR分析报告
    一、启用慢查询日志配置慢查询日志参数编辑MySQL配置文件(通常是my.cnf或my.ini),找到以下参数并进行设置。slow_query_log:将其设置为1以启用慢查询日志。例如:slow_query_log=1。long_query_time:定义查询执行时间的阈值,超过这个时间的查询会被记录到慢查询日志中。单......
  • MYSQL索引相关
    原sqlSELECTid,user_id,package_id,term_id,source,type,order_id,code_record_id,created_at,updated_at,version,is_deletedASdeletedFROMtbl_purchased_packageWHERE(ter......
  • MySQL双主配置
    1、配置的前置条件已知A服务器IP=192.168.0.11,B服务器IP=192.168.0.12建议使用相同版本的MySQL,若是小版本跨越一般是兼容的,如A的MySQL版本是5.7.1,B的MySQL版本是5.7.2;配置前需要保证两个数据库的数据一致,建议将A数据库同步到B数据库,以保证配置前A、B两台数据库的数据是一致的;......
  • Oracle、MySQL、ClickHouse的通用AES256加解密如何实现?
     Oracle、MySQL、ClickHouse的通用AES256加解密如何实现? 前段时间研究了加密算法aes,写了个文档,分享到博客上来。防。1  说明应XXX安全生产需求,对目标库目标表业务字段敏感信息进行加密密文存放,查询时通过解密得到明文进行数据使用,要求使用AES256。目前公司所使用主要......
  • MySQL数据库详细介绍:从入门到进阶
    MySQL是一个广泛使用的开源关系型数据库管理系统,被广泛应用于Web应用程序、企业级应用以及各种数据分析场景。本文将详细介绍MySQL数据库的基本概念、安装、配置、管理以及优化等方面的内容,帮助大家从入门到进阶了解MySQL。 一、MySQL安装可以通过以下链接下载MySQL安装包:......