Mysql中的索引

1,什么是索引,为什么要使用索引?

索引是帮助Mysql高效获取数据的排好序的数据结构。建立索引可以帮助我们快速检索我们需要的信息,减少磁盘的I/O次数,加快检索速度。索引的数据结构包括:二叉树,红黑树,Hash表,B-树等。

2,数据查询的方式

二叉查找树的方式查找信息

普通情况下,在一个二叉树中查找到5非常快速。只需要2步,但在某些极端情况下,如对于顺序插入信息的二叉树,查找到我们需要的信息就非常麻烦了。

红黑树

红黑树是一种自平衡二叉查找树,就是会自动平衡更新根节点和其它节点的位置,也就是说根节点和其它节点的位置是不固定,会根据插入的信息进行动态改变的。

按照1~5的顺序插入数据后,会重新排列分支节点的位置。

对于少量数据使用红黑树是完全可以的,但是一个项目的数据库中存储的数据都是10万条以上,再使用红黑树,树的度又会变得很大了。这个时候就可以使用B 树了。

B 树

B树是一种多路自平衡搜索树,它是一种特殊的平衡二叉树,但B树允许每个节点有更多的子节点。B树示意图如下:

B树的特点:

(1)所有键值分布在整个树中(2)任何关键字出现且只出现在一个节点中

(3)搜索有可能在非叶子节点结束(4)在关键字全集内做一次查找,性能逼近二分查找算法

比如我们想要找到主键为28的数据,过程如下:

1,根据根节点找到磁盘块1,进行一次I/O(磁盘的输入和输出)操作;

2,比较关键字28在区间(17,35),发现位于两者之间,找到P2指针;

3,根据P2指针找到磁盘块3,再进行一次I/O操作;

4,比较关键字28在区间(26,30),发现位于两者之间,找到磁盘块3的P2指针;

5,根据P2指针找到磁盘块8,再进行一次I/O操作;

6,在磁盘块8找到主键为28的数据。

在上面的过程中,只进行了3次磁盘I/O操作和3次内存查找操作,与二叉树和红黑树相比,对磁盘和内存读写次数减少了很多。不仅如此,B树中的各个节点都是可以横向扩展的,也就是说,不管有多少条数据,获取我们想要的数据对磁盘和内存的读写不超过四次。而B树四层的深度就可以满足百亿左右数据的使用了。

虽然B树很不错,但由于数据的键和值都储存在B树中,而有些数据中不仅仅包含数字,还可能包含大文本或是图片的二进制文件。那么这个二叉树立马就大了起来。而一个索引一般情况下也只有16K(可以将索引看做是表中特殊的页,Mysql中一个页大小只有16K),导致原本能够容纳上亿信息量的B树由于数据过多无法横向扩展。B+树应运而生。

B+树

B+树是在B-树基础上的一种优化,使其更适合实现外存储索引结构,在B+树中,所有数据记录节点都是按照键值大小顺序存放在同一层的叶子节点上,而非叶子节点上只存储key值信息,这样可以大大加大每个节点存储的key值数量,降低B+树的深度。B+树示意图如下:

所有数据记录节点都是按照键值大小顺序存放在同一层的叶子节点上,而非叶子节点上只存储key值信息,这是B+树与B树最大的区别。并且B+树的叶子结点都是以双向链表的方式连接的,因此对整棵树的遍历只需要一次线性遍历叶子结点即可。而且由于数据顺序排列并且相连,所以便于区间查找和搜索。而B树则需要进行每一层的递归遍历。相邻的元素可能在内存中不相邻。叶子节点中的data区域存储的不是和key值有关的数据表的信息,而是信息所在的磁盘地址。现在大部分数据库的索引类型都是B+树类型。

3.索引的本质

索引就是一颗B+树,一种为了磁盘或是其它直接存取辅助设计的一种平衡查找树,所有记录节点按照键值顺序存放在同一层的叶子节点上。B+树的根节点存放在内存中,而非叶子节点和叶子节点存放在磁盘中,所以查找一条信息最多只需要进行3次磁盘I/O操作。

4,索引的分类

4.1、从数据结构

4.1.1 全文索引

FULLTEXT INDEX 是针对一篇文章或是字符的索引,全文索引和sql语句“where xx like xxx%”功能差不多,但是在大量的数据面前,使用全文索引查询速度更快。

目前,Mysql版本在5.6以上的版本,InnoDB和MyISAM存储引擎都支持全文索引,5.6以下版本只有MyISAM支持全文索引。

那么多少条信息可以使用全文索引呢。

MySQL 中的全文索引,有两个变量,最小搜索长度和最大搜索长度,对于长度小于最小搜索长度和大于最大搜索长度的词语,都不会被索引。通俗点就是说,想对一个词语使用全文索引搜索,那么这个词语的长度必须在以上两个变量的区间内。我们可以通过以下语句进行查询。

show variables like '%ft%';

MyISAM的最小和最大长度分别为4,84;而InnoDB的为3,84;只有长度在这个区间中的信息才能正常使用全文索引,反之则不会获取到信息。

虽然我们能够使用全文索引,但是MySQL的全文索引效率很低,一般我们通过都第三方工具代替,如Elasticsearch。

//创建全文索引create fulltext index getcontent on account(content);//删除全文索引drop index getcontent on account;alter table account drop index getcontent;

4.1.2 B+树索引

这类索引是各种数据库中最常见的索引结构,也是InnoDB使用的索引。

4.1.3 Hash索引

哈希索引(hash index)基于哈希表实现,只有精确匹配索引所有列的查询才有效。对于每一行数据,存储引擎都会对所有的索引列计算一个哈希码(hash code),哈希码是一个较小的值,并且不同键值的行计算出来的哈希码也不一样.由于生成的哈希码是随机的,所以无法进行范围查找,只能进行等值比较查询,也就是只能进行=,!=,in,not in等操作。

4.1.4 R树索引

R树索引也被称为空间树索引。用于解决索引地理坐标,很好的解决了在高维空间搜索等问题。但在MySQL中不存在,其它数据库存在如SQLite。

4.2、从逻辑角度

4.2.1 非空索引

要求数据不能为空或是null。

alter table account add constraint CN_Cons check( content is not null)

4.2.2 唯一索引

要求数据内容不重复,但是可以为空或是NULL,但只能有一个NULL和一个空。

creatre unique index con account(content)

4.2.3 主键索引

是一种特殊的唯一索引,并且不能有空值

4.2.4 复合索引

用户可以在多个列上建立索引,叫复合索引。

create index ico on table1(id,name,content);

对于复合索引,在查询使用时,最好将条件顺序按找索引的顺序,这样效率最高;

select * from account where id= A and name= B and content= C;//会使用复合索引select * from account where  user= B and content= C;//不会使用复合索引

复合索引遵循最左匹配原则,即 where id=A and name=B可以用到索引,而 where name=B and content=C是不会用到复合索引的。因为B+树是按照数据库字段从左到右的顺序来建立搜索树的,B+树会优先比较id来确定下一步的所搜方向,如果id相同再依次比较name和content,最后得到检索的数据;但当查询语句没有id的数据的时候,B+树就不知道下一步该查哪个节点,因为建立搜索树的时候id就是第一个比较因子,必须要先根据id来搜索才能知道下一步去哪里查询。而如果缺少中间查询字段user时,数据库会先把id相同的信息查询到,然后在匹配content是C的数据。

4.3、从物理存储角度

4.3.1 聚簇索引

聚簇索引主要用于InnoDB表,数据表中的数据就是按顺序存储的,在物理上是连续的。将数据存储与索引放到了一块,因此一个表只能有一个聚簇索引。

我们在建立数据表时,会生成两个索引,主键索引和辅助索引;其中主键索引是根据主键自动生成的,如果没有主键索引,会自动将数据表中第一个唯一且非空的索引作为主键索引,如果还是没有会自动创建一个隐藏的名字为“GEN_CLUST_INDEX ”的聚簇索引。总之,一个 InnoDB 表只有一个聚簇索引,而且一定会有一个聚簇索引,如果不存在,Innodb 存储引擎会自动添加一个。而辅助索引则是我们人为建立的索引,也称为非聚簇索引。

通过其它字段建立的辅助索引的每条记录中都包含了该条记录的主键,主键索引的叶子节点包含了该主键所对应的数据信息。当我们根据某些条件查询数据时,会在辅助索引中获取满足查询条件的主键,然后使用主键检索到与之对应的叶子节点取得数据。

为什么辅助索引要使用主键作为‘指针’,而不用磁盘地址值作为’指针‘呢?

那是因为我们在进行行移动或者分裂数据页时(数据存储的位置发生变化),不需要更新辅助索引中的这个‘指针’。不管这个主键B+树的节点如何变化,辅助索引树都不受影响。

4.3.2 非聚簇索引

非聚簇索引主要用于MyISAM表,将数据存储与索引分开储存,非聚簇索引中也有主键索引和辅助索引,两个索引的储存位置是独立的,通过辅助键检索无需访问主键的索引树。虽然两个索引的结构看起来差不多,但是主键索引的叶子节点储存的是主键信息,而辅助索引的叶子节点储存的是辅助键,对于数据表来书没有任何差别,都是通过叶子节点直接获取到数据信息。所以对于MyISAM表,主键不是必须的。

4.3.3 区别

从上面来看,非聚簇索引比聚簇索引看起来要方便,非聚簇索引只要检索一次,而聚簇索引要检索两次,那么我们为什么还要使用聚簇索引呢?

这是因为聚簇索引中的主键索引和人为建立的辅助索引(非聚簇索引)都储存在一起的,当我们第一次访问这个表时,数据表的所有索引都已经加载到Buffer(缓冲区)了,之后再根据其它字段查询访问时,会在内存中完成,不必访问磁盘。节省了大量时间。而且按顺序存储的数据表要进行排序时,使用聚簇索引更加适合。同理,取出一定范围数据的时候,要使用聚簇索引。

当然,聚簇索引也有一定的缺点:

1.因为数据表的数据存储地址都是顺序的,所以更新聚簇索引列的代价很高,会强制将每个被更新的数据行移动到新的位置。
2.聚簇索引可能导致全表扫描变慢,尤其是行比较稀疏,或者由于页分裂导致数据存储不连续的时候。
3,如果主键比较大的话,那辅助索引将会变的更大,因为辅助索引的叶子存储的是主键值;过长的主键值,会导致非叶子节点占用占用更多的物理空间。

5,使用场景

1、不要索引数据量不大的表,对于小表来讲,表扫描的成本并不高。
2、不要设置过多的索引,在没有聚集索引的表中,最大可以设置249个非聚集索引,过多的索引首先会带来更大的磁盘空间,而且在数据发生修改时,对索引的维护是特别消耗性能的。
3、合理应用复合索引,有某些情况下可以考虑创建包含所有输出列的覆盖索引。
4、对经常使用范围查询的字段,可能考虑聚集索引。
5、避免对不常用的列,逻辑性列,大字段列创建索引。

(0)

相关推荐

  • 耗时3天,整整2W字干货讲解Mysql索引,简历上给我写精通Mysql

    索引概念 概念:索引是提高mysql查询效率的数据结构.总的一句话概括就是索引是一种提高查询效率的数据结构. 数据库查询是数据库的最主要功能之一.设计者们都希望查询数据的速度能尽可能地快,因此数据库系 ...

  • MySQL索引是怎么支撑千万级表的快速查找?

    本文作者:何建辉(公众号:org_yijiaoqian) 前言 在 MySQL 官方提到,改善操作性能的最佳方法 SELECT 在查询中测试的一个或多个列上创建索引.索引条目的作用类似于指向表行的指针 ...

  • 我想不通!MySQL 为什么使用 B 树来作索引?

    什么是索引? 所谓的索引,就是帮助 MySQL 高效获取数据的排好序的数据结构.因此,根据索引的定义,构建索引其实就是数据排序的过程. 平时常见的索引数据结构有: 二叉树 红黑树 哈希表 B Tree ...

  • MySQL索引底层:B+树详解

    前言 当我们发现SQL执行很慢的时候,自然而然想到的就是加索引.对于范围查询,索引的底层结构就是B+树.今天我们一起来学习一下B+树哈~ 公众号:「捡田螺的小男孩」 树简介.树种类 B-树.B+树简介 ...

  • 这篇 MySQL 索引和 B Tree 讲的太通俗易懂!

    来源:https://blog.csdn.net/b_x_p/article/details/86434387 作者:he_321 正确的创建合适的索引,是提升数据库查询性能的基础.在正式讲解之前,对 ...

  • 再有人问你MySQL索引原理,就把这篇文章甩给他!

    作者 l zyz1992 来源 l Hollis(ID:hollischuang) 索引,可能让好很多人望而生畏,毕竟每次面试时候 MySQL 的索引一定是必问内容,哪怕先撇开面试,就在平常的开发中, ...

  • 牛逼!MySQL 8.0 中的索引可以隐藏了… – Programming language

    MySQL 8.0 虽然发布很久了,但可能大家都停留在 5.7.x,甚至更老,其实 MySQL 8.0 新增了许多重磅新特性,比如栈长今天要介绍的 "隐藏索引" 或者 " ...

  • MySQL性能优化:MySQL中的隐式转换造成的索引失效

    数据库优化是一个任重而道远的任务,想要做优化必须深入理解数据库的各种特性.在开发过程中我们经常会遇到一些原因很简单但造成的后果却很严重的疑难杂症,这类问题往往还不容易定位,排查费时费力最后发现是一个很 ...

  • mysql在建表语句中添加索引

    普通索引创建 创建普通索引,即不添加 UNIQUE.FULLTEXT 等任何参数. [例]创建表名为 score 的数据表,并在该表的 id 字段上建立索引,SQL 语句如下: CREATE tabl ...

  • 在处理jsp读取mysql中遇到的问题记录

    在我第一次使用jdbc,来通过jsp读取mysql中遇到一些问题记录一下. 首先都是一个DBHelper.java的工具类, package util; import java.sql.Connect ...

  • mysql中cast() 和convert()的用法讲解

    一.在mysql操作中我们经常需要对数据进行类型转换.此时我们应该使用的是cast()或convert(). 二.两者的对比 相同点:都是进行数据类型转换,实现的功能基本等同 不同点:两者的语法不同, ...

  • 记一次MySQL中Waiting for table metadata lock的解决方法

    最近项目中的数据库查询经常挂起,应用程序启动后也报操作超时.测试人员就说数据库又挂了(貌似他们眼中的连接失败,查询无果都是挂了),通过 show processlist 一看,满屏都是 Waiting ...

  • MYSQL中UNION和UNION ALL的区别有哪些?

    在mysql中如何想要对两个结果集进行合并操作,可以使用UNION和UNION ALL,如果只是想要去除掉重复的记录,属于UNION ALL 即可,但是如何想要除掉没有重复行数据,就要使用Union. ...

  • Mysql数据库的索引类型有哪些?

    Java编程语言是一种简单.面向对象.分布式.解释型.健壮安全.与系统无关.可移植.高性能.多线程和动态的语言.如今Java已经广泛应用于各个领域的编程开发. MySQL索引类型: 1.普通索引 最基 ...

  • MySQL中JSON使用

    文章目录 前言 1.创建表和插入数据: 2.查询json中的使用字段: 3.json科普: 4.mysql中操作json的函数: 4.1 JSON_ARRAY:生成json数组. 4.2 JSON_O ...