Mysql索引

Posted lllllLiangjia

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mysql索引相关的知识,希望对你有一定的参考价值。

目录

1.定义

2.索引类型

哈希表

全文索引(FullText Key)

搜索树

二叉搜索树

平衡二叉树

“N叉”树

B树

B树与B+树的区别:

3.InnoDB 的索引模型

B+树索引模型

结构:

思考:

4.索引类型

4.1 主键索引(Primary Key)

4.2 非主键索引

4.3 索引使用情况

覆盖索引

索引下推 (Index Condition Pushdown)

5.索引维护

6.索引查询类型

全值匹配

最左前缀原则

匹配列前缀

匹配范围值

索引的优势

索引的缺点


1.定义

索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容。

mysql官方:索引是一种优化查询的数据结构

2.索引类型

哈希表

哈希表这种结构适用于只有等值查询的场景。范围查询不好使

全文索引(FullText Key)

全文索引主要是为了检索大文本数据中的关键字的信息,是目前搜索引擎数据库使用的一种技术。Mysql5.6 之前只有 MYISAM 引擎支持全文索引,在5.6版本中,InnoDB加入了对全文索引的支持,但是不支持中文全文索引.在5.7.6版本,MySQL内置了ngram全文解析器,用来支持亚洲语种的分词.

使用倒排索引(inverted index)来实现,它是在辅助表中存储了单词与单词自身在一个或多个文档中所在位置之间的映射。通常利用关联数组实现,并拥有两种表现形式。

全文索引有自己的语法格式,使用 match 和 against 关键字

select * from fulltext_test where match(content,tag) against('xxx xxx');

搜索树

二叉搜索树

特点:每个节点的左儿子小于父节点,父节点又小于右儿子。

时间复杂度是O(log(N))

平衡二叉树

为了维持O(log(N))的查询复杂度,你就需要保持这棵树是平衡二叉树。为了做这个保证,更新的时间复杂度也是O(log(N))

“N叉”树

查询一次节点就要访问一个数据块,为了尽量少地读磁盘,就用N叉树

以InnoDB的一个整数字段索引为例,这个N差不多是1200。这棵树高是4的时候,就可以存1200的3次方个值,这已经17亿了。考虑到树根的数据块总是在内存中的,一个10亿行的表上一个整数字段的索引,查找一个值最多只需要访问3次磁盘。其实,树的第二层也有很大概率在内存中,那么访问磁盘的平均次数就更少了。

B树

B树与B+树的区别:

单论B+树结构与B树结构那只是增加了叶子节点的单向指针,

InnoDB中使用的B+树叶子节点之间增加了双向指针,目的是为了范围查询双向遍历。

很多人说B树非叶子节点存储了数据,B+树没有存储数据,其实不对。B树和B+树节点的结构确定之后,里面存储什么数据完全是由使用这些结构的开发人员决定的,里面存储的数据与B树和B+树的结构没有任何关系,并不是它们的区别

3.InnoDB 的索引模型

B+树索引模型

每一个索引在InnoDB里面对应一棵B+树。

B-Tree通常意味着所有的值都是按照顺序存储的,并且每一个叶子页到根的距离相同。B+树上增加了顺序访问指针,也就是每个叶子节点增加一个指向相邻叶子节点的指针

一个节点存储多个元素,相对于完全平衡二叉树所以整棵树的高度就降低了,磁盘IO效率就降低了

data存的是数据本身。索引也是数据。数据和索引存在一个XX.IDB文件中,所以也叫聚集索引

结构:

非叶子节点: 索引值+指针

叶子节点: 索引值+数据+指向下一个叶结点的指针

思考:

B+树中一个节点页多大合适?

为一页或者页的倍数最合适。否则会造成资源浪费

一个节点页为1页(16k)就够了?

假如一行数据大小为1k,那么一个子叶就能存16条数据,也就是一个叶子节点能存16条数据。

再看非叶子节点,假设主键D为 bigint类型,那么长度为8B,指针大小在 innodb源码中为6B,一共就是14B那么一页里就可以存储16K/14B=1170个(主键+指针),那么一颗高度为2的B+树能存储的数据为1170*16=18720条,一颗高度为3的B+树能存储的数据为:1170*1170*16=21902400(千万级条)。所以在InnoDB中B+树高度一般为1-3层,它就能满足干万级的数据存储。在查找数据时一次页的查找代表一次IO,所以通过主键索引查询通常只需要1-3次IO操作即可查找到数据。所以也就回答了我们的问题,1页=16k这么设置是比较合适的,是适用大多数的企业的,当然这个值是可以修改的,所以也能根据业务的时间情况进行调整

4.索引类型

表中R1~R5的(ID,k)值分别为(100,1)、(200,2)、(300,3)、(500,5)和(600,6)

4.1 主键索引(Primary Key)

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

数据行的物理顺序与列值(一般是主键的那一列)的逻辑顺序相同,一个表中只能拥有一个聚集索引。

数据行的物理顺序与列值的顺序相同,如果我们查询id比较靠后的数据,那么这行数据的地址在磁盘中的物理地址也会比较靠后。而且由于物理排列方式与聚集索引的顺序相同,所以也就只能建立一个聚集索引了。

优点:

聚集索引的查询速度非常的快,叶子节点也都是有序的,定位到索引的节点,就相当于定位到了数据。

缺点:

更新代价大 

4.2 非主键索引

非主键索引的叶子节点内容是主键的值。在InnoDB里,非主键索引也被称为二级索引(secondary index)。

  1. 唯一索引(Unique Key) :唯一索引也是一种约束。唯一索引的属性列不能出现重复的数据,但是允许数据为 NULL,一张表允许创建多个唯一索引。 建立唯一索引的目的大部分时候都是为了该属性列的数据的唯一性,而不是为了查询效率。
  2. 普通索引(Normal Key)普通索引的唯一作用就是为了快速查询数据,一张表允许创建多个普通索引,并允许数据重复和 NULL。
  3. 前缀索引(Prefix Key) :前缀索引只适用于字符串类型的数据。前缀索引是对文本的前几个字符创建索引,相比普通索引建立的数据更小, 因为只取前几个字符。
  4. 空间索引(SPATIAL Key):空间索引是指依据空间对象的位置和形状或空间对象之间的某种空间关系按一定的顺序排列的一种数据结构 ,其中包含空间对象的概要信息,如对象的标识、外接矩形及指向空间对象实体的指针。使用

优点:

更新代价比聚集索引要小

缺点:

可能会二次查询(回表) ,

主键索引和普通索引的查询有什么区别?

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

4.3 索引使用情况

覆盖索引

如果一个索引包含所有需要查询的字段的值(索引的叶子节点中包含要查询的数据),我们就称之为“覆盖索引”

覆盖索引可以减少树的搜索次数,显著提升查询性能,所以使用覆盖索引是一个常用的性能优化手段。

例如:

建组合索引idx_age_name(age,name)。查询的字段id、age、name的值刚刚都在索引树上,只需扫描一次组合索引B+树即可,这就是实现了索引覆盖,此时的Extra字段为Using index表示使用了索引覆盖。

索引下推 (Index Condition Pushdown)

什么是索引下推?

在查询时,根据条件把符合的索引相关数据整条查询出来存储到server层,然后对这些符合前部分索引条件的行数据,再进行其它条件的where判断进行筛选。

如何查看一个语句是否使用了索引下推?

查看EXPLAINExtra列是否显示Using index condition

【没有索引下推之前】

现根据第一个索引字段从存储引擎中拉取数据到server层,然后在server层中对age进行数据过滤。

【有了索引下推之后】

根据该索引的所有字段条件来做数据筛选,将筛选之后的结果返回给server层。

索引下推限制

  • 对于InnoDB表,ICP只适用于辅助索引。因为ICP的目标是减少全表读的数量从而减少I/O操作。对于InnoDB聚集索引,完整的记录已经被读取到InnoDB缓冲区,在这种情况下使用ICP不能降低I/O
  • 与子查询相关的条件不能下推
  • 与存储函数相关的条件不能下推。

5.索引维护

索引是对数据的排序,那么当对表中的数据进行增删改操作时,都需要去维护修改内容涉及到的B+树索引。所以咋进行增删改操作时,可能需要额外的时间进行一些记录移动,页面分裂、页面回收等操作来维护好排序。

  • 如果要插入的数据页已满,那就要申请一个新的数据页,然后挪动部分数据过去。这个过程称为页分裂。性能会受影响
  • 当相邻两个页由于删除了数据,利用率很低之后(小于50%),会将数据页做合并。合并的过程,可以认为是分裂过程的逆过程。

6.索引查询类型

全值匹配

最左前缀原则

因为B+树先是按照b列的值排序的,在b列的值相同的情况下才使用c列进行排序,而现在跳过b列直接根据c的值去査找,这是做不到的

匹配列前缀

只匹配某一列值的开头部分。

当想要通过后缀匹配索引查询,要如何做?

如果我们想要查询以com为后缀的网址的话可以将url逆序存储。moc.udiab.www。这样查询就可以用where url like 'moc%',这样就可以用到索引了。

匹配范围值

索引的优势

  • 索引大大减少了服务器需要扫描的数据量。
  • 索引可以帮助服务器避免排序和临时表

MySQL 的流程是这样的,扫描所有行,把所有行加载到内存后,再按 age 排序生成一张临时表,再把这表排序后将相应行返回给客户端,更糟的,如果这张临时表的大小大于 tmp_table_size的值(默认为 16 M),内存临时表会转为磁盘临时表,性能会更差;

但是如果加了索引,索引本身是有序的,所以从磁盘读的行数本身就是按 age 排序好的,也就不会生成临时表,就不用再额外排序 

  • 索引可以将随机IO变为顺序IO

索引的缺点

  • 创建索引和维护索引需要耗费许多时间。当对表中的数据进行增删改的时候,如果数据有索引,那么索引也需要动态的修改,会降低 SQL 执行效率。
  • 索引需要使用物理文件存储,也会耗费一定空间。

以上是关于Mysql索引的主要内容,如果未能解决你的问题,请参考以下文章

mysql索引

面试官:MySQL 数据库查询慢,除了索引问题还可能是什么原因?

Mysql 索引-2

MySQL索引类型

MYSQL索引总结

mysql索引总结----mysql 索引类型以及创建