MySQL 索引 :哈希索引、B+树索引、全文索引

文章目录

  • 索引
    • 引言
    • 常见的索引
  • 哈希索引
    • 自适应哈希索引
  • B+树索引
    • 聚集索引
    • 非聚集索引
    • 使用方法
    • 联合索引
    • 最左前缀匹配规则
    • 覆盖索引
  • 全文索引
    • 使用方法


索引

引言

为什么需要索引?

倘若不使用索引,查找数据时,MySQL必须遍历整个表。而表越大,查询的时间则越长,则数据库的效率也就越低。而索引就类似于书籍的目录,可以帮助我们快速的定位、检索到需要的数据行,对提高数据库的性能有着很大的帮助。

在MySQL中,索引是一种特殊的文件,其中包含着对数据表里所有记录的引用指针。各类索引有各自的数据结构实现。

索引优缺点

优点:

  • 大大加快了数据检索的速度
  • 使用要求低,所有的列类型都可以被索引,也就是可以给任意字段设置索引

缺点:

  • 索引需要占用物理空间,建立的索引越多则需要的空间越大
  • 创建和维护索引需要耗费时间,并且时间随着数据量的增加而增加
  • 当对表中的数据进行增加、删除、修改的时候,索引也要动态的维护,如果一张表经常需要增删改,那么有索引的话就降低了数据的更新速度。

适用场景

  • 数据量较大,并且经常对这些列进行查询。
  • 该数据库表的插入、修改操作频率较低。

常见的索引

因为 MySQL 中索引是在 存储引擎层 实现的,所以并没有统一的索引标准,换言之:

  • 不同存储引擎支持的索引类型并不一样。
  • 而即使多个存储引擎支持同一种类型的索引,其底层的实现也可能不同。

由于 InnoDB存储引擎MySQL 数据库中使用最为广泛,所以下面的讨论主要以 InnoDB 为例。

InnoDB存储引擎 中,主要支持以下三种常见的索引:B+树索引、哈希索引、全文索引。


哈希索引

如不了解哈希可移步哈希 :哈希冲突、负载因子、哈希函数、哈希表、哈希桶

原理:通过除留余数法将键值转换为哈希值,并将数据存储对应的槽中,如果出现了哈希冲突,则使用链地址法进行解决,将数据插入对应槽中的链表。

由于哈希是直接通过哈希值来将数据映射到对应位置,所以哈希索引对于等值查询的效率特别高,但是也正因为这个特性,使得哈希查找在面对范围查找的时候就毫无用武之地了。

自适应哈希索引

InnoDB存储引擎 会监控对表上各个索引页的查询,如果它观察到建立哈希索引可以带来速度提升,则会自行建立哈希索引,这也就是 自适应哈希索引。即会自动根据 访问频率和模式 来为 热点数据 建立哈希索引。

哈希索引是数据库自身自动创建并使用的,人工无法对其进行干预。


B+树索引

如不了解B+树可移步数据结构 | B树、B+树、B*树

比起哈希索引,B+树索引的优势主要在于排序查找以及区间查找

在数据库中,B+树索引可以分为聚集索引(主键索引)非聚集索引(辅助索引),它们之间的区别在于叶子节点中存放的是否是一整行的信息(即用户数据)

PS:叶子节点那一层存储的是表,而具体的某一个叶子节点才是存储列。


聚集索引

聚集索引其实就是索引数据在同一个数据结构中。

由于 InnoDB存储引擎 中表的数据按照主键顺序存放,所以聚集索引也就是按照每张表的主键来构造出一颗B+树。由于数据真正的排序方式只能有一种,所以在每张表中只能存在着一个聚集索引

这颗B+树的非叶子节点存放的是数据的索引,而叶子节点存放的即为整张表的行记录数据,所以我们通常也将叶子节点称为数据页,并且每个叶子节点之间用双向链表进行连接。
在这里插入图片描述
聚集索引对于主键的排序查找和范围查找速度非常快,并且由于叶子节点就是数据,所以只需要查找一次就可以得到结果。


非聚集索引

在这里插入图片描述
对于 非聚集索引(辅助索引) 来说,叶子节点并不包含行记录的全部数据,而是包含了主键的值。

也就是说,我们需要在非聚集索引中查找到主键,再通过主键聚集索引中查找到具体的值,也就是需要两次查找。所以非聚集索引其实也就是一个二级索引

在这里插入图片描述
基于以上特性,由于辅助索引的存在并不会影响数据聚集索引中的存在方式,因此每张表中可以有多个辅助索引。


使用方法

创建主键约束(PRIMARY KEY)、唯一约束(UNIQUE)、外键约束(FOREIGN KEY)时,会自动创建对应列的索引。

查看索引

SHOW INDEX FROM 表名 

创建

CREATE INDEX 索引名 ON 表名(字段名)
或者
ALTER TABLE 表名 ADD {KEY | INDEX} 索引名

删除

DROP INDEX 索引名 ON 表名

联合索引

联合索引即对表上的多个列进行索引:
在这里插入图片描述
联合索引和普通的B+树不同的地方在于它具有多个键值,键值按照从左往右的优先级以此对键值的大小进行排序,例如:上图有两个键值,首先会先按照第一个键值的大小进行排序,当第一个键相同时,再按照第二个键的大小进行排序。

因为以上特性,联合索引具有最左前缀匹配规则,当不满足规则时则不会使用联合索引,而是进行全索引扫描。


最左前缀匹配规则

就以上述数据进行举例,此时以键值 (a, b) 构建联合索引

SELECT * FROM TABLE WHERE a = xxx AND b = xxx 、
SELECT * FROM TABLE WHERE a = xxx 
SELECT * FROM TABLE WHERE b = xxx 

对于以上几条查询语句来说,虽然看起来差不多,但是效率却大相径庭。

对于前两句来说,它们是可以使用联合索引的,因为无论是按照 a 作为条件,或者是 ab 作为条件。因为前面也说过了,联合索引的排序是按照从左往右优先的,所以当前两句都是优先根据 a 进行索引搜索,不会出现问题。

但对于 b=xxx 则无法适用以上性质,因为在联合索引中,后面的主键只有在前面的主键相同时才会具有有序性,而单独适用它的时候显然数据是无序的,所以这时只能进行全索引扫描

对于范围查找也是这么一个道理,假设此时联合索引的主键为(a, b, c)

SELECT * FROM TABLE WHERE a > 3 AND b > 3
SELECT * FROM TABLE WHERE a > 3 AND b > 3 AND c > 3 
SELECT * FROM TABLE WHERE a > 3 AND c > 3

同样按照上面的规则,前两种查询都可以适用联合索引,因为其遵循了从左至右的匹配原则,而第三条因为跳过了 b,此时的数据是无序的,无法适用索引。


覆盖索引

覆盖索引即从辅助索引中就可以得到查询的记录,而不需要查询聚集索引中的记录。使用覆盖索引的一个好处就是由于辅助索引中不包含整行的所有记录,所以它的大小要远远小于聚集索引,因此可以减少大量的 I/O 操作。

由于辅助索引中叶子节点存放的数据就是主键,所以当我们要查找主键,或者通过主键来统计数量的时候,就可以使用覆盖索引来完成。


全文索引

在之前版本中只有 InnoDB 并不支持全文检索,而在 InnoDB1.2.x 版本之后,InnoDB 也加入了全文检索的功能。

全文索引即根据部分段落、句、词从数据库中查询除全文的技术,即根据部分查询词获取对应的文档。

主要依据倒排索引这一数据结构来实现,这一数据结构通常也在搜索引擎中进行使用。

这里就简要的介绍一下 InnoDB 中的倒排索引。其拥有两种表现形式:

  • inverted file index(倒排文件索引)
    表现形式 {单词, 单词所在的文档ID)
  • full inverted index(全文倒排索引)
    表现形式{单词, (单词所在文档ID,在具体文档的位置)

例如我们存在以下数据:
在这里插入图片描述
并将其构建成 inverted file index(倒排文件索引) 的形式:
在这里插入图片描述
此时我们就建立起了各个单词与其对应文档的一个映射关系。

接着建立 full inverted index(全文倒排索引)

在这里插入图片描述
此时在之前的基础上,我们不仅确定了单词所在的文章,还确定了其所在文章中的对应位置,虽然比起 inverted file index来 说更加复杂,占据的空间也更多,但是却能更好的定位数据,并且扩充一些其它的搜索特性。


使用方法

创建全文索引

CREATE FULLTEXT INDEX 索引名 ON 表名(字段名);

查找方法

MATCH(要匹配的列) AGAINST(要查找的内容) 
  1. 自然语言查询(Natural Language),即普通的包含关键词的搜索,例如:
SELECT * FROM (表名) WHERE MATCH(匹配列) AGAINST(查询内容)
  1. Boolean,这个模式允许使用 IN BOOLEAN MODE修饰符 来进行全文检索,当使用该修饰符时,查询字符串的前后字符都会有特殊含义。例如 +- 分别代表了该单词必须出现或者一定没出现。

这句查询即匹配包含 查询词1 并且不包含 查询词2 的结果:

SELECT * FROM 表名 
WHERE MATCH (要匹配的列) AGAINST ('+查询词1 -查询词2' IN BOOLEAN MODE);

该模式所有选项如下:
在这里插入图片描述
全文查询的结果依据相关度进行降序排序,相关度计算依据如下:

  • 查询词是否在文档中出现过
  • 查询词在文档中出现的次数
  • 查询词在索引列中的数量
  • 包含查询词的文档数

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

服装店怎么引流和吸引顾客 服装店铺收银系统来配合

实体店的同城引流和经营是实体经济的一个重要的一环,今天我们来分享服装行业的实体店铺怎么引流和吸引、留住顾客,并实现复购。大家点个收藏,不然划走就再也找不到了,另外可以点个关注,下次有新的更好的招,…

约瑟夫环(丢手绢问题)

文章目录问题描述思路代码实现问题描述 有 1~N 个数字,从 1~m 依次报数,数到 m 的数字要被删掉,求最后剩下的数字是? 思路 第一次报数第二次报数1n-m12n-m2……m-2n-2m-1n-1m被删掉了m11m22……n-1n-1-mnn-m 通过上面的表格&…

MySQL 锁的相关知识 | lock与latch、锁的类型、简谈MVCC、锁算法、死锁、锁升级

文章目录lock与latch锁的类型MVCC一致性非锁定读(快照读)一致性锁定读(当前读)锁算法死锁锁升级lock与latch 在了解数据库锁之前,首先就要区分开 lock 和 latch。在数据库中,lock 和 latch 虽然都是锁&…

Hibernate使用原生SQL适应复杂数据查询

HQL尽管容易使用,但是在一些复杂的数据操作上功能有限。特别是在实现复杂的报表统计与计算,以及多表连接查询上往往无能为力,这时可以使用SQL(Native SQL)实现HQL无法完成的任务。 1、使用SQL查询 使用SQL查询可以通过…

MySQL 存储引擎 | MyISAM 与 InnoDB

文章目录概念innodb引擎的4大特性索引结构InnoDBMyISAM区别表级锁和行级锁概念 MyISAM 是 MySQL 的默认数据库引擎(5.5版之前),但因为不支持事务处理而被 InnoDB 替代。 然而事物都是有两面性的,InnoDB 支持事务处理也会带来一些…

MySQL 事务 | ACID、四种隔离级别、并发带来的隔离问题、事务的使用与实现

文章目录事务ACID并发带来的隔离问题幻读(虚读)不可重复读脏读丢失更新隔离级别Read Uncommitted (读未提交)Read Committed (读已提交)Repeatable Read (可重复读)Serializable (可串行化)事务的使用事务的实现Redoundo事务 事务指逻辑上的一组操作。 …

MySQL 备份与主从复制

文章目录备份主从复制主从复制的作用备份 根据备份方法的不同,备份可划分为以下几种类型: 热备(Hot Backup) : 热备指的是在数据库运行的时候直接备份,并且对正在运行的数据库毫无影响,这种方法在 MySQL 官方手册中又…

C++ 流的操作 | 初识IO类、文件流、string流的使用

文章目录前言IO头文件iostreamfstreamsstream流的使用不能拷贝或对 IO对象 赋值条件状态与 iostate 类型输出缓冲区文件流fstream类型文件模式文件光标函数tellg() / tellp()seekg() / seekp()向文件存储内容/读取文件内容string流istringstreamostringstream前言 我们在使用 …

Hibernate 更新部分更改的字段 hibernate update

Hibernate 中如果直接使用 Session.update(Object o);或则是Session.updateOrUpdate(Object o); 会把这个表中的所有字段更新一遍。 如: ExperClass4k e new ExperClass4k(); e.setTime(time); e.setQ_num(q_num); e.setK(k); if (str "finch_fix")…

C++ 类的行为 | 行为像值的类、行为像指针的类、swap函数处理自赋值

文章目录概念行为像值的类行为像指针的类概念引用计数动态内存实现计数器类的swap概念swap实现自赋值概念 行为像值的类和行为像指针的类这两种说法其实蛮拗口的,这也算是 《CPrimer》 翻译的缺点之一吧。。。 其实两者的意思分别是: 行为像值的类&am…

C++ 右值引用 | 左值、右值、move、移动语义、引用限定符

文章目录C11为什么引入右值?区分左值引用、右值引用move移动语义移动构造函数移动赋值运算符合成的移动操作小结引用限定符规定this是左值or右值引用限定符与重载C11为什么引入右值? C11引入了一个扩展内存的方法——移动而非拷贝,移动较之拷…

且谈关于最近软件测试的面试

前段时间有新的产品需要招人,安排和参加了好几次面试,下面就谈谈具体的面试问题,在面试他人的同时也面试自己。 面试问题是参与面试同事各自设计的,我也不清楚其他同事的题目,就谈谈自己设计的其中2道题。 过去面试总是…

C++ 多态 | 虚函数、抽象类、虚函数表

文章目录多态虚函数重写重定义(参数不同)协变(返回值不同)析构函数重写(函数名不同)final和override重载、重写、重定义抽象类多态的原理虚函数常见问题解析虚函数表多态 一种事物,多种形态。换…

C++ 运算符重载(一) | 输入/输出,相等/不等,复合赋值,下标,自增/自减,成员访问运算符

文章目录输出运算符<<输入运算符>>相等/不等运算符复合赋值运算符下标运算符自增/自减运算符成员访问运算符输出运算符<< 通常情况下&#xff0c;输出运算符的第一个形参是一个 非常量ostream对象的引用 。之所以 ostream 是非常量是因为向流写入内容会改变…

C++ 重载函数调用运算符 | 再探lambda,函数对象,可调用对象

文章目录重载函数调用运算符lambdalambda等价于函数对象lambda等价于类标准库函数对象可调用对象与function可调用对象function函数重载与function重载函数调用运算符 函数调用运算符必须是成员函数。 一个类可以定义多个不同版本的调用运算符&#xff0c;互相之间应该在参数数…

C++ 运算符重载(二) | 类型转换运算符,二义性问题

文章目录类型转换运算符概念避免过度使用类型转换函数解决上述问题的方法转换为 bool显式的类型转换运算符类型转换二义性重载函数与类型转换结合导致的二义性重载运算符与类型转换结合导致的二义性类型转换运算符 概念 类型转换运算符&#xff08;conversion operator&#…

Tomcat中JVM内存溢出及合理配置

Tomcat本身不能直接在计算机上运行&#xff0c;需要依赖于硬件基础之上的操作系统和一个Java虚拟机。Tomcat的内存溢出本质就是JVM内存溢出&#xff0c;所以在本文开始时&#xff0c;应该先对Java JVM有关内存方面的知识进行详细介绍。 一、Java JVM内存介绍 JVM管理两种类型的…

俄罗斯农民乘法 | 快速乘

文章目录概念概念 俄罗斯农民乘法经常被用于两数相乘取模的场景&#xff0c;如果两数相乘已经超过数据范围&#xff0c;但取模后不会超过&#xff0c;我们就可以利用这个方法来拆位取模计算贡献&#xff0c;保证每次运算都在数据范围内。 A 和 B 两数相乘的时候我们如何利用加…

Linux网络编程 | socket选项设定 及 网络信息API

文章目录读取和设置 socket 选项SO_REUSEADDRSO_RCVBUF 和 SO_SNDBUFSO_RCVLOWAT 和 SO_SNDLOWATSO_LINGER 选项网络信息APIgethostbyname 和 gethostbyaddrgetservbyname 和 getservbyportgetaddrinfogetnameinfo读取和设置 socket 选项 正如 fcntl 系统调用是控制文件描述符…

Linux | 高级I/O函数

文章目录创建文件描述符的函数pipe函数dup函数、dup2函数读取或写入数据readv函数、writev函数零拷贝sendfile函数splice函数tee函数进程间通信——共享内存mmap函数 和 munmap函数控制文件描述符fcntl函数创建文件描述符的函数 pipe函数 不再赘述&#xff0c;详情见我的另一…