目录

  • 简介
  • 索引结构(树)
    • 为什么用树,而不用哈希表
    • BTree索引
    • B+Tree索引
    • 聚簇索引与非聚簇索引
  • 索引分类
  • 性能分析
    • 索引创建场景

简介

MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。可以得到索引的本质:索引是数据结构。

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

一般来说索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上。

优点:
1、类似大学图书馆建书目索引,提高数据检索的效率,降低数据库的IO成本。
2、通过索引列对数据进行排序,降低数据排序的成本,降低了CPU的消耗。

缺点:
1、虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。每次更新添加了索引列的字段,都会调整因为更新所带来的键值变化后的索引信息。
2、实际上索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录,所以索引列也是要占用空间的

索引举例:(用树结构做索引)
左边是数据表,一共有两列七条记录,最左边的是数据记录的物理地址。

为了加快Col2的查找,可以维护一个右边所示的二叉查找树,每个节点分别包含索引键值和一个指向对应数据记录物理地址的指针,这样就可以运用二叉查找在一定的复杂度内获取到相应数据,从而快速的检索出符合条件的记录。

索引结构(树)

如何通过索引加快数据库表的查询速度呢?为了方便讲解,我们限定于数据库表只包含下面这样两个查询需求:
1、select* from user where id=1234;
2、select *from user where id>1234 and id<2345;(按区间)

为什么用树,而不用哈希表

哈希表按值查询的性能很好,时间复杂度是O(1),但它不能支持按照区间快速查找数据,因此无法满足要求。同理,尽管平衡二叉查找树查询性能很高,时间复杂度为O(logn),而且对树进行中序遍历,可以输出有序的数据序列,但也无法满足按照区间快速查找数据的需求。

为了支持按照区间快速查找数据,我们对二叉查找树进行改造,将二叉查找树的叶子节点用链表串起来,如果要查找某个区间的数据,只需要用区间的起始值,在树中进行查找,当定位到有序链表中的某个节点之后,再从这个节点开始顺着有序链表往后遍历,直到有序链表中的节点数据值大于区间终止值为止。

又因为树上的很多操作的时间复杂程度与树的高度成正比,降低的树的高度,就能减少磁盘IO操作。因此我们把索引构建成m叉树(m>2),详细介绍可看后文。

BTree索引

在介绍B+树之前,先来了解一下B树。

1、初始化介绍
一颗b树,浅蓝色的块我们称之为一个磁盘块,可以看到每个磁盘块包含几个数据项(深蓝色所示)和指针(黄色所示),如磁盘块1包含数据项17和35,包含指针P1、P2、P3。P1表示小于17的磁盘块,P2表示在17和35之间的磁盘块,P3表示大于35的磁盘块。

注意:
真实的数据只存在于叶子节点,即3、5、9、10、13、15、28、29、36、60、75、79、90、99。(而且是多条数据组成的数据区间:3~ 5,… … ,90~ 99)

非叶子节点不存储真实的数据,只存储指引搜索方向的数据项,如17、35并不真实存在于数据表中。

2、查找过程
如果要查找数据项29,那么首先会把磁盘块1由磁盘加载到内存,此时发生一次IO,在内存中用二分查找确定29在17和35之间,锁定磁盘块1的P2指针,内存时间因为非常短(相比磁盘的IO)可以忽略不计,通过磁盘块1的P2指针的磁盘地址把磁盘块3由磁盘加载到内存,发生第二次IO,29在26和30之间,锁定磁盘块3的P2指针,通过指针加载磁盘块8到内存,发生第三次IO,同时内存中做二分查找找到29,结束查询,总计三次IO。

B+Tree索引

B+树和B树类似,B+树是B树的改进版。
即:m叉查找树与有序链表构建成的树就是B+树,也就是要存储的树索引

如图:B+树和B树的主要区别有以下两点:
1、B+树的叶子节点用链表来串联。
查找某个区间的数据,只需要用区间的起始值,在树中进行查找,当定位到有序链表中的某个节点之后,再从这个节点开始顺着有序链表往后遍历,直到有序链表中的节点数据值大于区间终止值为止。

2、B+树中的任何节点都不存储真实数据,只是用来索引。
B树直接通过叶子节点获取到数据;而B+树每个叶子节点存储数据行的键值和地址信息,当查询到某个叶子节点时,通过叶子节点的地址找到真实的数据信息。

聚簇索引与非聚簇索引

聚簇索引并不是一种单独的索引类型,而是一种数据存储方式。
术语‘聚簇’表示数据行和相邻的键值聚簇的存储在一起。

聚簇索引的好处:
按照聚簇索引排列顺序,查询显示一定范围数据的时候,由于数据都是紧密相连,数据库不不用从多个数据块中提取数据,所以节省了大量的io操作。

聚簇索引的限制:
1、对于mysql数据库目前只有innodb数据引擎支持聚簇索引,而Myisam并不支持聚簇索引。
2、由于数据物理存储排序方式只能有一种,所以每个Mysql的表只能有一个聚簇索引。一般情况下就是该表的主键。
3、为了充分利用聚簇索引的聚簇的特性,所以innodb表的主键列尽量选用有序的顺序id,而不建议用无序的id,比如uuid这种。

如下图,左侧的索引就是聚簇索引,因为数据行在磁盘的排列和索引排序保持一致。

索引分类

单值索引
即一个索引只包含单个列,一个表可以有多个单列索引

随表一起建索引:
CREATE TABLE customer (
id INT(10) UNSIGNED  AUTO_INCREMENT ,
customer_no VARCHAR(200),
customer_name VARCHAR(200),
PRIMARY KEY(id),
KEY (customer_name)
);单独建单值索引:
CREATE  INDEX idx_customer_name ON customer(customer_name); 删除索引:
DROP INDEX idx_customer_name  on customer;

唯一索引
索引列的值必须唯一,但允许有空值

随表一起建索引:
CREATE TABLE customer (
id INT(10) UNSIGNED  AUTO_INCREMENT ,
customer_no VARCHAR(200),
customer_name VARCHAR(200),PRIMARY KEY(id),KEY (customer_name),UNIQUE (customer_no)
);单独建唯一索引:
CREATE UNIQUE INDEX idx_customer_no ON customer(customer_no); 删除索引:
DROP INDEX idx_customer_no on customer ;

主键索引
设定为主键后数据库会自动建立索引,innodb为聚簇索引

随表一起建索引:
CREATE TABLE customer (
id INT(10) UNSIGNED  AUTO_INCREMENT ,
customer_no VARCHAR(200),
customer_name VARCHAR(200),PRIMARY KEY(id)
);CREATE TABLE customer2 (
id INT(10) UNSIGNED   ,
customer_no VARCHAR(200),
customer_name VARCHAR(200),PRIMARY KEY(id)
);单独建主键索引:
ALTER TABLE customer add PRIMARY KEY customer(customer_no);  删除建主键索引:
ALTER TABLE customer drop PRIMARY KEY ;  修改建主键索引:
必须先删除掉(drop)原索引,再新建(add)索引

复合索引
即一个索引包含多个列

随表一起建索引:
CREATE TABLE customer (
id INT(10) UNSIGNED  AUTO_INCREMENT ,
customer_no VARCHAR(200),
customer_name VARCHAR(200),PRIMARY KEY(id),KEY (customer_name),UNIQUE (customer_name),KEY (customer_no,customer_name)
);单独建索引:
CREATE  INDEX idx_no_name ON customer(customer_no,customer_name); 删除索引:
DROP INDEX idx_no_name  on customer ;

性能分析

索引创建场景

哪些情况需要创建索引
1、主键自动建立唯一索引
2、频繁作为查询条件的字段应该创建索引
3、查询中与其它表关联的字段,外键关系建立索引
4、单键/组合索引的选择问题, 组合索引性价比更高
5、查询中排序的字段,排序字段若通过索引去访问将大大提高排序速度
6、查询中统计或者分组字段

哪些情况不要创建索引
1、表记录太少
2、经常增删改的表或者字段
原因:提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件
3、Where条件里用不到的字段不创建索引
4、过滤性不好的不适合建索引

MySQL索引(B树、B+树)相关推荐

  1. 为什么MySQL索引要使用 B+树,而不是其它树形结构?

    一个问题? InnoDB一棵B+树可以存放多少行数据?这个问题的简单回答是:约2千万 为什么是这么多呢? 因为这是可以算出来的,要搞清楚这个问题,我们先从InnoDB索引数据结构.数据组织方式说起. ...

  2. 16kb等于多少b_面试官:MySQL索引为何选择B+树?

    声明 本文所述的各种数据结构(二叉树等),均不考虑重复值的情况,本文简述各种数据结构的区别仅仅只是为了理解MySQL索引的需要而做的铺垫. 什么是索引 提起索引,大家都知道,建立索引可以让数据库查询更 ...

  3. MySQL索引底层:B+树详解

    前言 当我们发现SQL执行很慢的时候,自然而然想到的就是加索引.对于范围查询,索引的底层结构就是B+树.今天我们一起来学习一下B+树哈~ 树简介.树种类 B-树.B+树简介 B+树插入 B+树查找 B ...

  4. mysql为什么不使用二叉树,MYSQL 索引为什么使用B+树,而不是 B 树,二叉树:

    如何评价索引的好坏: 数据库服务器有两种存储介质,硬盘和内存,为了数据安全,索引需要存放在硬盘上,这样在硬盘上进行查询时,就会产生硬盘的I/O操作,索引的查找次数也就是硬盘I/O的操作次数,所以索引需 ...

  5. Mysql 索引为啥使用B+树?不用哈希或B树?红黑树?

    哈希索引:单个记录的增删改查效率高,时间复杂度是O(1):但对于范围查询需要全表扫描: B树: 1 范围查询时效率比B+树低(B树的叶子结点缺少有序链表): 2 内部节点(非叶子结点)既存储数据也存储 ...

  6. 为什么MySQL索引更适合B+树而不是二叉树、B树

    一 数据库为什么使用B+树 1. 与二叉树相比 二叉树相比于顺序查找的确减少了查找次数,但是在最坏情况下,二叉树有可能退化为顺序查找.而且就二叉树本身来说,当数据库的数据量特别大时,其层数也将特别大. ...

  7. mysql索引怎么设计_mysql索引设计

    mysql索引设计 1.B树与B+树的区别? B-Tree:一个节点可以拥有大于2个子节点的平衡多叉树,所有关键字在整颗树中出现,包括在非叶子节点也能命中, 叶子节点之间没有链表 B+Tree:每个叶 ...

  8. MySQL索引的前世今生

    MySQL索引的前世今生 什么是索引 索引的优缺点 B+Tree索引的前世今生 为什么 MySQL 索引选择了 B+树而不是 B 树? 应该知道的索引知识点 使用索引时的注意事项 引用: https: ...

  9. 面试热点话题:聊聊MySQL索引“B+Tree”的前世今生,

    小伙伴想精准查找自己想看的MySQL文章?喏 → MySQL江湖路 | 专栏目录   面试一说起MySQL,我们总会提到B+Tree索引,你对B+Tree索引了解么,它有哪些特性,优势在哪里,和B树有 ...

  10. mysql专题(一):深入理解Mysql索引底层数据结构与算法

    Mysql索引 帮助MySQL高效获取数据的排好序的数据结构. 1.索引 一种为表的行提供快速查找功能的数据结构,通常通过形成表示特定列或列集 的所有值的 树结构(B 树)来实现. InnoDB表总是 ...

最新文章

  1. 从源码分析DEARGUI之异步调用函数对比
  2. Linux命令详解:[7]获得命令帮助
  3. 国货之光业务增长背后的技术支持 - 完美日记的云原生实践
  4. php中如何让这段东西不显示出来,数据显示处理,该怎么处理
  5. mysql mode_mysql中的sql_mode
  6. java hotspot 是什么_什么是HotSpot
  7. paros web中间件攻击、扫描、监控
  8. [手把手教]discuzX2插件制作教程__最菜鸟级别的入门坎 【三】
  9. python字典(一)
  10. mysql 读取oracle数据_Python中Pandas通过read_sql方法从Mysql或Oracle数据库中读取数据帧(DataFrame)...
  11. HTML5 前端原生 WebSocket 通信
  12. PMBOK第七版即将来袭!你是否做好准备迎接新考纲+新教材的PMP考试?
  13. ghost for linux 教程,今天解决了ghost for linux的问题
  14. 《信息与编码》考试复习笔记6----第六章连续信源熵和信道容量相关例题
  15. android仿小米日历,实现一个仿小米日历控件
  16. Spring学习笔记(二十三)——实现网站微信扫码登录获取微信用户信息Demo
  17. RTX3070和2080Ti 哪个好
  18. Spring 使用 ref 和 depends-on 属性的使用
  19. ktor启动报错:Module function cannot be found for the fully qualified name 'ApplicationKt.module'
  20. 爬虫入门一:BeautifulSoup解析豆瓣即将上映的电影信息

热门文章

  1. 【MVC购物车】购买和加入购物车功能
  2. 苹果ceo乔布斯_苹果CEO乔布斯因胰腺癌去世,医生提醒,胰腺不好有四个信号
  3. 【推荐系统】YoutubeDNN召回
  4. addBatch()和executeBatch()
  5. jmete并发数控制
  6. SPI接收数据异常问题总结
  7. 微软Surface低端版本将问世
  8. 遍历所有盘符和对应的设备
  9. Bash 脚本如何创建临时文件:mktemp 命令和 trap 命令教程
  10. Redis学习—过期机制