公众号首发-推荐阅读原文-格式更好看

点击阅读原文

点击阅读原文

点击阅读原文

一、导读

在MySQL中,不仅为主键创建的聚簇索引选用的数据结构是B+Tree,像辅助索引,二级索引、覆盖索引、联合索引等等其实都是B+Tree。

二、聚簇索引

MySQL默认为 int 类型的主键创建一个聚簇索引。这棵B+Tree是如何设计、如何长高可以参考上一篇文章。

https://mp.weixin.qq.com/s/TwcNEzEWg0PpN0Ra_kiTag

这颗B+Tree之所以叫做聚簇索引是因为它的叶子节点中存储的是完整的数据行,也就是说你拿着id从这棵树的根索引上检索,一直到叶子节点并且定位到特定的数据页后,你是可以去除完整的数据行来的!(所有列都有)

三、二级索引

二级索引也被大家称为辅助索引,其实每个索引都是对应一棵独立的B+Tree,而且他们都有这个特性:后面的数据页中的索引值均比它前面的数据页中的索引值大,并且都会通过页分裂的机制保证这个特性一致成立。

不同的是不同索引的叶子节点中存储的数据是不一样的!对于二级索引来说它的叶子节点中存储的不再是完整的数据行,而是id值。

比如表里面有 id、age、name、addr四列,且name列是二级索引。然后你的SQL是这样的

select * from table
where name = 'tom';

那就会先扫描name列这颗B+Tree,找到name=‘tom’所在的叶子节点,叶子节点中存储的只有name = ‘tom’的这行数据在表中的id值。于是再拿着这个id值去聚簇索引中重新查询,这个动作我们称为:“回表”

你可以像下面这样创建二级索引

CREATE INDEX [index name] ON [table name]([column name]);

或者

ALTER TABLE [table name] ADD INDEX [index name]([column name]);

四、联合索引

4.1、什么是联合索引

联合索引也叫复合索引,说白了就是多个字段一起组合成一个索引。

像下面这样使用 id + title 组合在一起构成一个联合索引

CREATE TABLE `text` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
`content` text NOT NULL,
PRIMARY KEY (`id`,`title`)
) ENGINE=InnoDB AUTO_INCREMENT=3691 DEFAULT CHARSET=utf8 # 或者通过这种方式添加联合索引
alter table text add INDEX `t3_index_title_content` (`title`,`content`);
  • 如果我们像上图那样创建了索引,我们只要保证 id+title 两者结合起来全局唯一就ok
  • 建立联合索引同样是需要进行排序的,排序的规则就是按照联合索引所有列组成的字符串的之间的先后顺序进行排序,,如a比b优先。

4.2、左前缀原则

使用联合索引进行查询时一定要遵循左前缀原则。

什么是左前缀原则呢?

就是说想让索引生效的话,一定要添加上第一个索引,只使用第二个索引进行查询的话会导致索引失效。

比如上面创建的联合索引,假如我们的查询条件是 where id = '1' 或者 where id = '1' and title = '唐诗宋词' 索引都会不失效。

但是如果我们不使用第一个索引id,像这样 where title = '唐诗' ,结果就是导致索引失效。

问:如果我不遵循做前缀原则,一定不能使用聚簇索引吗?

回答:不是的!可以看下面的例子:

# t3表中有3个索引,如下:
# id:聚簇索引
# x1:唯一的二级索引
# x1_x3_x2:联合索引
explain select * from t3 where x2 = 'fdc1a9f7d94ece2b68b7d3e3be1b0f3b';

可以看到,x2列没有单独的索引。但是sql的执行计划选择去联合索引树中扫全表,也不会去聚簇索引中全表扫描。

这里只需要大概看懂这个执行计划就ok,下一讲详细讲!

4.3、联合索引的分组&排序

还是使用这个例子:

CREATE TABLE `text` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
`content` text NOT NULL,
PRIMARY KEY (`id`,`title`)
) ENGINE=InnoDB AUTO_INCREMENT=3691 DEFAULT CHARSET=utf8

demo1: 当我们像下面这样写sql时,就会先按照id进行排序。当id相同时再按照title进行排序。

select * form text order by id, title;

demo2: 当我们像下面这样写sql时,就会先将id相同的划分为一组,再将title相同的划分为一组。

select id,title form text group by id, title;

demo3: ASC和DESC混用, 其实大家都知道底层使用B+树,本身就是有序的。要是不加限制的话,默认就是ASC。反而是混着使用就使得索引失效。

select * form text order by id ASC, title DESC;

另外补充一点:如果你的group by xxx列,这一列没有索引时,mysql会 Using temporary 也就是中间表来实现你的分组操作,效率是很低的! 而如果有索引的话,直接走索引就可以实现 group by。

五、覆盖索引

覆盖索引其实和二级索引没啥区别,只不过是查询方式不同而让它省去了回表的操作而已。

还是这个例子:

比如表结构是这样的

CREATE TABLE `text` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
`content` text NOT NULL,
PRIMARY KEY (`title`,`content`)
) ENGINE=InnoDB AUTO_INCREMENT=3691 DEFAULT CHARSET=utf8

然后你的SQL是这样的

select content from table
where title = 'all in';

你会发现,其实select中期望得到的内容已经全部存在于辅助索引中了,所以不需要再使用id进行回表操作也能得到正确的返回值。

这其实在一定程度上也说明了别总是动不动就select *,能走覆盖索引尽量使用覆盖索引。哪怕是不得不进行一次回表操作也尽量使用limit、where条件限制一下!

六、倒排索引

InnoDB中是存在倒排索引和全文检索的概念的!

MySQL的inverted index同B+Tree索引一样。另外会使用一张辅助表来存储单词和document之间的映射关系。

比如它的倒排索引表长下面这样:

Number Text Documents
1 old 1,4
2 hot 2,5

解读上表:old这个单词在document1和doc4中出现过。 单词hot在doc2、doc5中出现过

full inverted index关联数据长下面这样

Number Text Documents
1 code (1,4), (2,5)
2 review (3,5),(5,8)

解读上表:单词code在doc1的第4个单词的位置上出现了。同理单词review也类似。


但是一般我们一说到全文检索或者是倒排索引往往都会直观的想到:Elasticsearch 这款NoSQL

因为InnoDB存储引擎的全文检索是存在限制的:

  • 每张表只能有一个全文检索的索引
  • 由多列组合而成的全文检索的索引列必须使用相同的字符集
  • 不支持没有单词界定符的语言,如:中文、日语、韩语
  1. MySQL的修仙之路,图文谈谈如何学MySQL、如何进阶!(已发布)
  2. 面前突击!33道数据库高频面试题,你值得拥有!(已发布)
  3. 大家常说的基数是什么?(已发布)
  4. 讲讲什么是慢查!如何监控?如何排查?(已发布)
  5. 对NotNull字段插入Null值有啥现象?(已发布)
  6. 能谈谈 date、datetime、time、timestamp、year的区别吗?(已发布)
  7. 了解数据库的查询缓存和BufferPool吗?谈谈看!(已发布)
  8. 你知道数据库缓冲池中的LRU-List吗?(已发布)
  9. 谈谈数据库缓冲池中的Free-List?(已发布)
  10. 谈谈数据库缓冲池中的Flush-List?(已发布)
  11. 了解脏页刷回磁盘的时机吗?(已发布)
  12. 用十一张图讲清楚,当你CRUD时BufferPool中发生了什么!以及BufferPool的优化!(已发布)
  13. 听说过表空间没?什么是表空间?什么是数据表?(已发布)
  14. 谈谈MySQL的:数据区、数据段、数据页、数据页究竟长什么样?了解数据页分裂吗?谈谈看!(已发布)
  15. 谈谈MySQL的行记录是什么?长啥样?(已发布)
  16. 了解MySQL的行溢出机制吗?(已发布)
  17. 说说fsync这个系统调用吧! (已发布)
  18. 简述undo log、truncate、以及undo log如何帮你回滚事物! (已发布)
  19. 我劝!这位年轻人不讲MVCC,耗子尾汁! (已发布)
  20. MySQL的崩溃恢复到底是怎么回事? (已发布)
  21. MySQL的binlog有啥用?谁写的?在哪里?怎么配置 (已发布)
  22. MySQL的bin log的写入机制 (已发布)
  23. 删库后!除了跑路还能干什么?(已发布)
  24. 自导自演的面试现场,趣学数据库的10种文件(已发布)
  25. 大型面试现场:一条update sql执行都经历什么?(已发布)
  26. 大型翻车现场:如何实现记录存在的话就更新,如果记录不存在的话就插入。(已发布)
  27. 视频+图文串讲:MySQL 行锁、间隙锁、Next-Key-Lock、以及实现记录存在的话就更新,如果记录不存在的话就插入如何保证并发安全(已发布)
  28. 自导自演的面试现场:说说char 和 varchar的区别你了解多少?。(已发布)
  29. 自导自演的面试现场之--你竟然不了解MySQL的组提交?。(已发布)
  30. 全网最清楚的:MySQL的insert buffer和change buffer 串讲(已发布)
  31. Double Write并不难理解
  32. 简述MySQL的三大范式
  33. 盘点各种登陆数据库的方式
  34. 面试现场:join联表的注意点、有哪些联表查询方式、真题...

    35.心里有点树

    36.心里有点B树

    37.聚簇索引到底是怎么回事?是如何长高的?

    38.8分钟回顾MySQL的索引

白日梦的MySQL专题(第38篇文章)8分钟回顾MySQL的索引的更多相关文章

  1. 这篇文章告诉你MYSQLB+树具体索引数据组织明细内容

    面试题:InnoDB中一棵B+树能存多少行数据?   一.InnoDB 一棵 B+ 树可以存放多少行数据? InnoDB 一棵 B+ 树可以存放多少行数据? 这个问题的简单回答是:约 2 千万. 为什 ...

  2. 白日梦的MySQL专题(第33篇):各种登陆MySQL的骚操作

    阅读原文 系列文章公众号首发,点击阅读原文 前置知识 我们想登陆到mysql中前提是肯定需要一个用户名和密码:比如 mysql -uroot -proot 在mysql中用户的信息会存放在 mysql ...

  3. Golang分布式爬虫:抓取煎蛋文章|Redis/Mysql|56,961 篇文章

    --- layout: post title: "Golang分布式爬虫:抓取煎蛋文章" date: 2017-04-15 author: hunterhug categories ...

  4. mysql中的中文乱码解决方案, 全部是 这篇文章的内容: https://www.52jbj.com/jbdq/18755.html

    我们自己鼓捣mysql时,总免不了会遇到这个问题:插入中文字符出现乱码,虽然这是运维先给配好的环境,但是在自己机子上玩的时候咧,总得知道个一二吧,不然以后如何优雅的吹牛B. 如果你也遇到了这个问题,咱 ...

  5. 安装篇五:安装MySQL(5.6.38版本)

    #1.MySQL安装 #1.准备环境 # No1:关闭:(iptables)selinux # No2:下载好安装包(这里使用 mysql-5.6.38.tar.gz 包安装) # No3:安装依赖包 ...

  6. 如果有人问你 MySql 怎么存取 Emoji,把这篇文章扔给他

    01.前言 Emoji 在我们生活中真的是越来越常见了,几乎每次发消息的时候不带个 Emoji,总觉得少了点什么,似乎干巴巴的文字已经无法承载我们丰富的感情了.对于我们开发者来说,如何将 Emoji ...

  7. 如何优雅的备份MySQL数据?看这篇文章就够了

    大家好,我是一灯,今天一块学习一下如何优雅安全的备份MySQL数据? 1. 为什么要备份数据 先说一下为什么需要备份MySQL数据? 一句话总结就是:为了保证数据的安全性. 如果我们把数据只存储在一个 ...

  8. MySQL Performance-Schema(二) 理论篇

    MySQL Performance-Schema中总共包含52个表,主要分为几类:Setup表,Instance表,Wait Event表,Stage Event表Statement Event表,C ...

  9. Python自动化 【第十二篇】:Python进阶-MySQL和ORM

    本节内容 数据库介绍 mysql 数据库安装使用 mysql管理 mysql 数据类型 常用mysql命令 创建数据库 外键 增删改查表 权限 事务 索引 python 操作mysql ORM sql ...

随机推荐

  1. 用PS给视频磨皮美颜

    无意间找到的,但是一个10分钟的视频渲染了我一天的时间,但是效果是不错的 参考视频链接 https://www.bilibili.com/video/BV1b7411m74e 视频中涉及的添加插件链接 ...

  2. 使用 cmake 来搭建跨平台的应用程序框架:C语言版本

    目录 一.前言 二.示例代码说明 1. 功能描述 2. 文件结构 3. cmake 构建步骤 4. Utils 目录说明 5. Application 目录说明 三.Linux 系统下操作步骤 1. ...

  3. 说了你可能不信leetcode刷题局部链表反转D92存在bug,你看了就知道了

    一.题目描述 找出数组中重复的数字 > 在一个长度为 n 的数组 nums 里的所有数字都在 0-n-1 的范围内.数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次. ...

  4. [软件开发的目录规范、区分py文件的两种用途]

    [软件开发的目录规范] 软件开发的目录规范 bin: 执行文件 conf: 存放配置文件相关代码 core: 存放源文件,业务逻辑相关代码 db: 存放数据库文件,主要用于与数据库交互 lib: 存放 ...

  5. 【秒懂音视频开发】23_H.264编码

    本文主要介绍一种非常流行的视频编码:H.264. 计算一下:10秒钟1080p(1920x1080).30fps的YUV420P原始视频,需要占用多大的存储空间? (10 * 30) * (1920 ...

  6. [笔记] 《我的第一本c++书》

    函数 优秀函数的五个要点 函数的返回值:直接返回和间接返回(指针) 在函数的入口处对参数有效性进行检验:if语句,断言(assert) 如果函数有返回值,不可返回一个指向函数体内局部对象的指针或引用 ...

  7. gdb 调试,当发现程序退出,需要定位程序退出位置时。

    在进入gdb后设置,执行下面语句 handle SIGSEGV nopass handle SIGSEGV nostop 执行程序,触发问题,gdb侧执行c 故障出现时,执行bt,显示堆栈调用.

  8. Bash技巧:使用 set 内置命令帮助调试 shell 脚本

    Bash技巧:使用 set 内置命令帮助调试 shell 脚本 霜鱼片发布于 2020-02-03   在 bash 中,可以使用 set 内置命令设置和查看 shell 的属性.这些属性会影响 sh ...

  9. 【转载】linux 设备管理器 图形hardinfo 字符 lshw lspci

    在ubuntu中怎样启动类似windows中的 设备管理器 sudo apt-get install hardinfo lspci sudo lshw everestubuntu下的"设备管 ...

  10. 通过format学习,python的内部方法是面象对象的-python面向对象

    1.常用的形式 s ="{0} {0} qqq {0} xxx {1}".format('dog','cat')print(s) 结果:dog dog qqq dog xxx ca ...