MySQL索引结构详细解析

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

简介

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

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

优点:

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索引 详细解析的文章就介绍到这了,更多相关MySQL 索引内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 一文搞懂MySQL索引页结构

    目录 1.前言 2.索引页结构 2.1FileHeader 2.2PageHeader 2.3UserRecords 2.4Infimum&Supremum 2.5PageDirectory 2.6FileTrailer 3.总结 1. 前言 「页」是InnoDB管理存储空间的基本单位,也是内存和磁盘交互的基本单位.也就是说,哪怕你需要1字节的数据,InnoDB也会读取整个页的数据,下次读取的数据如果恰巧也在这个页里,就能命中缓存了.写也是一样的,写数据前要先把页加载到内存,然后在内存中修改,该

  • MySQL优化中B树索引知识点总结

    为什么要进行SQL优化呢?很显然,当我们去写sql语句时: 1会发现性能低 2.执行时间太长, 3.或等待时间太长 4.sql语句欠佳,以及我们索引失效 5.服务器参数设置不合理 SQL语句执行过程分析 1.编写过程: 编写过程就是我们平常写sql语句的过程,也可以理解为编写顺序,以下就是我们编写顺序: select from join on where 条件 group by 分组 having过滤组 order by排序 limit限制查询个数 我们虽然是这样去写的,但是它mysql的引擎去

  • 浅谈MySQL的B树索引与索引优化小结

    MySQL的MyISAM.InnoDB引擎默认均使用B+树索引(查询时都显示为"BTREE"),本文讨论两个问题: 为什么MySQL等主流数据库选择B+树的索引结构? 如何基于索引结构,理解常见的MySQL索引优化思路? 为什么索引无法全部装入内存 索引结构的选择基于这样一个性质:大数据量时,索引无法全部装入内存. 为什么索引无法全部装入内存?假设使用树结构组织索引,简单估算一下: 假设单个索引节点12B,1000w个数据行,unique索引,则叶子节点共占约100MB,整棵树最多20

  • 一文了解MySQL二级索引的查询过程

    目录 前言 联合索引 总结 前言 聚簇索引就是innodb默认创建的基于主键的索引结构,而且表里的数据就是直接放在聚簇索引里,作为叶节点的数据页: 基于主键的数据搜索:从聚簇索引的根节点开始进行二分查找,一路找到对应数据页,基于页目录就直接定位到主键目标数据. 若想对其它字段建立索引,甚至是基于多个字段建立联合索引,此时索引结构又是咋样? 假设对其他字段建立索引,如name.age之类,都是一样原理.比如你插入数据时: 把完整数据插入聚簇索引的叶节点的数据页,同时维护好聚簇索引 为你其他字段建立

  • MySQL与PHP的基础与应用专题之索引

    概述 从今天开始, 小白我将带领大家一起来补充一下 数据库的知识. 索引 索引 (Index) 是一种特殊的数据结构, 类似于图书的目录. 索引能够极大的提升数据库的查询效率. 如果没有索引, 在查询数据时必须扫描表中的说有记录才能找出符合条件的记录, 这种全表扫描的查询效率非常低. 索引的种类 描述 普通索引 最基本的索引, 没有任何限制, 仅加速查询 唯一索引 索引列的值必须唯一, 但允许有空值 主键索引 一种特殊的唯一索引, 不允许有空值 复合索引 两个或多个列上的索引被称作符合索引 全文

  • 一文弄懂MySQL索引创建原则

    目录 一.适合创建索引 1.字段的数值有唯一性限制 2.频繁作为Where查询条件的字段 3.经常Groupby和Orderby的列 4.Update.Delete的where条件列 5.Distinct字段需要创建索引 6.多表Join连接操作时,创建索引注意事项 7.使用列的类型小的创建索引 8.使用字符串前缀创建索引 9.区分度高的列适合作为索引 10.使用最频繁的列放到联合索引的左侧 11.在多个字段都要创建索引的情况下,联合索引由于单值索引 二.不适合创建索引 1.在where中使用不

  • Mysql数据库表中为什么有索引却没有提高查询速度

    背景 时间过得太快了,春节假期感觉光速般就结束了,转眼间就要继续搬砖上班了.紧接着很快就要进入金三银四的求职面试高峰期,程序猿小枫还没有找到令自己感到满意的工作.就算是在过年放假期间也在拼命的准备技术面试,这不他又梳理了下之前面试过程中面试官经常问到的关于数据库方面的一道面试题,我们来一起帮小枫看看有没有遗漏的地方吧. 面试题目--问题 面试官:看你的简历中有提到过曾经进行过索引优化的工作,那我就问问你,假设数据库表中有索引,但是进行SQL数据查询还是很慢,这种情况下应该怎么分析查询慢的原因?

  • MySQL索引结构详细解析

    目录 简介 索引结构(树) 为什么用树,而不用哈希表 BTree索引 B+Tree索引 聚簇索引与非聚簇索引 索引分类 性能分析 索引创建场景 简介 在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法.这种数据结构,就是索引. 一般来说索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上. 优点: 1.类似大学图书馆建书目索引,提高数据检索的效率,降低数据库的IO成本. 2.通过

  • MySQL索引事务详细解析

    目录 一.索引 1.概念 2.作用 3.缺陷 4.使用场景 5.使用 1.查看索引 2.创建索引 3.删除索引 6.案例 二.事务 1.为什么使用事务 2.事务的概念 3.使用 4.特性 一.索引 1.概念 索引是一种特殊的文件,包含着对数据表里所有记录的引用指针,可以对表中的一列或者多列创建索引,并指定索引的类型,各类索引有各自的数据结构实现. (这里对于索引也只是简单了解,写了些皮毛) 更浅显易懂的来说:数据库的数据保存在硬盘,硬盘不知道具体保存在哪个位置,索引就是用来告诉硬盘数据在哪个位置

  • Mysql中复制详细解析

    1.mysql复制概念 指将主数据库的DDL和DML操作通过二进制日志传到复制服务器上,然后在复制服务器上将这些日志文件重新执行,从而使复制服务器和主服务器的数据保持同步.复制过程中一个服务器充当主服务器(master),而一个或多个其它服务器充当从服务器(slaves).主服务器将更新重新写入二进制日志文件,并维护文件的一个索引以跟踪日志循环.这些日志可以记录发送到从服务器的更新.当一个从服务器连接主服务器时,它通知主服务器.从服务器在日志中读取的最后一次成功更新的位置.从服务器接受从那时起发

  • 浅析MySQL索引结构采用B+树的问题

    目录 1.B树和B+树 2.原因分析 3.总结 一位6年经验的小伙伴去字节面试的时候被问到这样一个问题,为什么MySQL索引结构要采用B+树?这位小伙伴从来就没有思考过这个问题.只因为现在都这么卷,后面还特意查了很多资料,他也希望听听我的见解. 另外,我花了1个多星期把往期的面试题解析配套文档准备好了,一共有10万字,想获取的小伙伴可以在我的煮叶简介中找到. 1.B树和B+树 一般来说,数据库的存储引擎都是采用B树或者B+树来实现索引的存储.首先来看B树,如图所示. B树是一种多路平衡树,用这种

  • MySQL索引下推详细

    目录 1.最左前缀原则 2.回表 3.索引下推 前言: 索引下推(ICP)是针对MySQL使用索引从表中检索数据行的情况的优 在没有索引下推的情况下,MySQL通过存储引擎遍历索引来定位表中的数据行并将它们返回给MySQl服务器,服务器再进行WHERE条件的判断,确认是否将数据行加入结果集. 开启索引下推,且WHERE条件部分可以仅使用索引中的列来评估,这时MySQL服务器会将这部分WHERE条件下推到存储引擎,接着存储引擎使用索引条目评估推送的索引条件,仅当满足该条件时才从表中进行读取 索引下

  • MySQL读写分离原理详细解析

    目录 一.读写分离的概念 二.引入中间件MyCat 三.MyCat服务端口和管理端口 一.读写分离的概念 读写分离是基于主从复制来实现的.在实际的应用环境中,肯定是读操作多,就像我们在电商平台上去购买东西,可能看了100个也就买了一两个.所以读操作永远比写这种更新操作多很多.所以我们基于主从复制的读写分离配置,就是让一个主库专门用来做数据的修改,写的时候专门在主库上写,主库通过主从复制把数据的更改通过binlog同步到从库上去,那么其他的客户端查询的请求都会最终映射到从库上去,而我们一个主库带上

  • Mysql 索引结构直观图解介绍

    一.模拟创建原始数据 下图中,左边是自己方便说明,模拟的数据.引擎为mysiam~ 右边是用EXCEL把它们随机排列后的一个正常仿真数据表,把主键按照1-27再排列(不随机的话我在模拟数据时本来就是按顺序写的,再加索引看不大出这个索引排序的过程) 也就是说右边的数据,使我们要测试的原始数据,没建索引前是这样排序的,后边所有的数据都是以这个为依准进行的,这样更好看索引生成后的排序效果. 该表有4个字段(id,a,b,c),共21行数据 二.创建索引 a 如下图,当创建索引a以后,在该索引结构中,从

  • 关于MySQL索引的深入解析

    前言 我们知道,索引的选择是优化器阶段的工作,但是优化器并不是万能的,它有可能选错所要使用的索引.一般优化器选择索引考虑的因素有:扫描行数,是否排序,是否使用临时表. 使用explain分析sql explain是很好的自测命令,勤于使用explain有助于我们写出更合理的sql语句以及建立更合理的索引: mysql> explain select * from t where (a between 1 and 1000) and (b between 50000 and 100000) ord

  • 简单谈谈Mysql索引与redis跳表

    摘要 面试时,交流有关mysql索引问题时,发现有些人能够涛涛不绝的说出B+树和B树,平衡二叉树的区别,却说不出B+树和hash索引的区别.这种一看就知道是死记硬背,没有理解索引的本质.本文旨在剖析这背后的原理,欢迎留言探讨 问题 如果对以下问题感到困惑或一知半解,请继续看下去,相信本文一定会对你有帮助 mysql 索引如何实现 mysql 索引结构B+树与hash有何区别.分别适用于什么场景 数据库的索引还能有其他实现吗 redis跳表是如何实现的 跳表和B+树,LSM树有和区别呢 解析 首先

  • 快速了解MySQL 索引

    MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度. 打个比方,如果合理的设计且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索引的MySQL就是一个人力三轮车. 索引分单列索引和组合索引.单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引.组合索引,即一个索包含多个列. 创建索引时,你需要确保该索引是应用在 SQL 查询语句的条件(一般作为 WHERE 子句的条件). 实际上,索引也是一张表,该表保存了主键与索引字

随机推荐