谈谈MySql索引
刚刚学习完丁奇老师《MySql 实战 45 讲》专栏中的索引部分,图文并茂的风格解开了我之前的许多疑惑,并且学习到许多新的东西,在此做个笔记,方便后续复习。由于 MySql 中存在多种存储引擎,每种存储引擎的实现方式都不太一样,而 InnoDB 在现在是比较流行的存储引擎,因此以下内容都是基于 InnoDB 讨论的。
索引是如何存储的
InnDB 索引是基于 N叉树实现的,为什么要使用 N叉树而不是二叉树呢?这是因为 MySql 中的数据都是存储在磁盘中的,我们查找数据都要进行 IO 操作,IO 操作比 CPU 运行的速度慢了一个等级,使用二叉树存储数据时,当我们从一个节点出发,要找它的子节点,就得进行一次 IO 操作,当数据库存储的数据多了之后,二叉树的层数变高,进行数据查找时 IO 操作也变多了。为了减少数据查询时的 IO 操作,InnDB 底层是使用 N叉树存储的,这个 N 取决于数据块的大小。
主键索引、非主键索引
上面说到,InnoDB 索引是基于 N叉树实现的,但是一个表我们需要建立的索引个数不止一个,因此每建立一个索引,InnoDB 就会创建一颗 N叉树来维护该索引数据,索引树建立完之后 InnDB 是如何通过索引找出我们所需要的数值的呢?
假设有一张表是这个样子的:
create table T(
id int primary key,
k int not null,
name varchar(16),
index(k))engine = InnDB;
)
这张表显示创建了一个索引 k,还包含一个默认的主键索引 id,InnDB 是按照如下方式来存储这两颗索引树的:
可以看到,主键索引的叶子节点是一个数据块,每个数据块就是一个行记录,包含 id 、k、name 的值,这就叫做主键索引,而索引 k 的叶子节点包含的数据是 id 值,这就是非主键索引。在这个表中,当我们需要根据某个 k 的值查找对应的 name 值,需要先根据 k 的值找出对应的 id 值,再根据 id 值查找对应的数据块,从数据块中才可以得知 name 的值。在 InnDB 里,主键索引也被称为聚簇索引,非主键索引也被称为二级索引。
覆盖索引
上面说到当使用二级索引查找其他字段值时,需要查找两颗索引树才可以找到对应字段的值,这是因为二级索引的叶子节点只包含主键值,如果在二级索引的叶子节点已经包含了我们要查找的内容,那么就可以减少一次查询,提升性能。例如刚刚的那张表,我们需要根据 k 值来找 id,此时二级索引的叶子节点已经包含了我们需要的数据,我们称此为覆盖索引。
我们可以根据具体的业务场景来创建覆盖索引,比如根据身份证 id 查找身份证号这个需求是很常见的,我们就可以给身份证 id 和身份账号建立一个联合索引,这样根据身份证 id 找出来的数据块就包含了身份证号,不用再根据主键去寻找身份证号了。
索引重建
这个是丁奇老师在专栏里面留下的问题:对于上面例子中的 InnDB 表 T,如果要重建索引 k,两个 SQL 语句可以这么写:
alter table T drop indexk;
alter table T add index(k);
如果要重建主键索引,也可以这么写:
alter table T drop primary key;
alter table T add primary key(id);
对于上面两个重建索引的做法,有不合适的地方吗?为什么?有更好的方法吗?
回答:上面的语句中,重建索引 k 的方式合理,但是重建主键的过程不合理。不论是删除主键还是创建主键,都会将整个表重建,所以连着执行两个语句,第一个语句就白做了,这两个语句,可以使用
alter table T engine = InnDB
代替。
该索引是否是必须的
这是老师留下的另一个问题:DBA 小吕在入职新公司的时候,就发现自己接手维护的库里面,有这么一个表,表结构定义类似这样的:
CREATE TABLE 'geek' (
`a` int(11) NOT NULL,
`b` int(11) NOT NULL,
`c` int(11) NOT NULL,
`d` int(11) NOT NULL,
PRIMARY KEY (`a`, `b`),
KEY `c` (`c`),
KEY `ca` (`c`, `a`),
KEY `cb` (`c`, `b`)
)
公司的同事告诉他,由于历史原因,这个表需要 a、b 做联合主键,这个小吕理解了。但是,学过本章的内容的小吕又纳闷了,既然主键包含了 a、b 这两个字段,那意味这单独在字段 c 上创建一个索引,就已经包含了这三个字段,为什么要创建 “ca”、“cb” 这两个索引?同事告诉它,是因为他们的业务里面有这样的两种语句:
select * from geek where c=N order by a limit 1;
select * from geek where c=N order by b limit 1;
问题是,这位同事的解释对吗,为了这两个查询模式,这两个索引是否都是必须的?为什么呢?
回答:我们一个一个来分析,首先是主键索引(a、b),主键索引先按照 a 排序,然后按照 b 排序,索引 c 就是按照 c 进行排序,在叶子节点中包含主键,即先按照 c 排序,然后按照 a 排序,接着按照 b 排序。索引 ca 先按照 c 排序,然后按照 a 排序,主键部分包含 b,这样看的话它和索引 c 存储的内容是一样的。索引 cb 先按照 c 排序,然后按照 b 排序,主键部分包含 a。经过上面分析,索引 ca 是可以去掉的,因为它的作用和索引 c 是一样的。
专栏推荐
丁奇老师的这个专栏从底层出发,并且会结合平时的业务场景来讲解 MySql,虽然刚开始没学多久,但是受益匪浅,上面只是我个人的笔记,如果大家有兴趣可以通过下面的二维码去购买对应的课程,学生还有五折哦!
谈谈MySql索引的更多相关文章
- 谈谈MySQL 索引
1.索引是什么 索引(Index)是帮助MySQL高效获取数据的数据结构.我们可以简单理解为:索引的目的在于提高查询效率. 2.原理 索引的数据结构是B+树,原理图如下 关于B+树的详细介绍,可以参见 ...
- 谈谈MySQL的索引
目录 索引 前言 是什么 B树 B+树 B树和B+树结构上异同 有什么用 怎么用 索引 前言 总所周知,数据库查询是数据库的最主要功能之一.我们都希望查询数据的速度能尽可能的快.而支撑这一快速的背后就 ...
- 谈谈MySQL数据表的类型(转)
谈谈MySQL数据表的类型 通常意义上,数据库也就是数据的集合,具体到计算机上数据库可以是存储器上一些文件的集合或者一些内存数据的集合. 我们通常说的MySql数据库,sql server数据库等等其 ...
- 谈谈MySQL支持的事务隔离级别,以及悲观锁和乐观锁的原理和应用场景?
在日常开发中,尤其是业务开发,少不了利用 Java 对数据库进行基本的增删改查等数据操作,这也是 Java 工程师的必备技能之一.做好数据操作,不仅仅需要对 Java 语言相关框架的掌握,更需要对各种 ...
- 浅谈Mysql索引
文章原创于公众号:程序猿周先森.本平台不定时更新,喜欢我的文章,欢迎关注我的微信公众号. 我们都知道,数据库索引可以帮助我们更加快速的找出符合的数据,但是如果不使用索引,Mysql则会从第一条开始查询 ...
- 索引很难么?带你从头到尾捋一遍MySQL索引结构,不信你学不会!
前言 Hello我又来了,快年底了,作为一个有抱负的码农,我想给自己攒一个年终总结.自上上篇写了手动搭建Redis集群和MySQL主从同步(非Docker)和上篇写了动手实现MySQL读写分离and故 ...
- 带你从头到尾捋一遍MySQL索引结构(1)
从一个简单的表开始 create table user( id int primary key, age int, height int, weight int, name varchar(32) ) ...
- 带你从头到尾捋一遍MySQL索引结构(2)
前言 Hello我又来了,快年底了,作为一个有抱负的码农,我想给自己攒一个年终总结.索性这次把数据库中最核心的也是最难搞懂的内容,也就是索引,分享给大家. 这篇博客我会谈谈对于索引结构我自己的看法,以 ...
- 第36讲 谈谈MySQL支持的事务隔离级别,以及悲观锁和乐观锁的原理和应用场景
在日常开发中,尤其是业务开发,少不了利用 Java 对数据库进行基本的增删改查等数据操作,这也是 Java 工程师的必备技能之一.做好数据操作,不仅仅需要对 Java 语言相关框架的掌握,更需要对各种 ...
随机推荐
- (3)html-webpack-plugin的作用
在内存中生成index.html页面 在前面的内容中我们已经知道了如何在内存中打包main.js并引入到页面中. 同样的,我们也可以把index.html也打包放入到内存中. 安装html-webpa ...
- Python Ethical Hacking - VULNERABILITY SCANNER(3)
Polish the Python code using sending requests in a session Class Scanner. #!/usr/bin/env python impo ...
- Python numpy 浮点数精度问题
Python numpy 浮点数精度问题 在复现FP(fictitious play, Iterative solution of games by fictitious play-page393)算 ...
- 洛谷P1063.能量项链
题目描述 在Mars星球上,每个Mars人都随身佩带着一串能量项链.在项链上有N颗能量珠.能量珠是一颗有头标记与尾标记的珠子,这些标记对应着某个正整数.并且,对于相邻的两颗珠子,前一颗珠子的尾标记一定 ...
- Bootstrap 3 -> 4 : 居中布局的变化
我们知道,Bootstrap布局的核心是栅格系统,一行有12个栅格. 比如,我想让两个宽度400px左右的div居中显示. 这个时候,我们可以利用栅格的列偏移功能. <div class=&qu ...
- reCAPTCHA无法加载?一个小工具就可以轻松解决!
Chrome用户可以在应用商店搜索gooreplacer安装,或者点我下载,然后打开chrome://extensions/,将下载的crx文件拖入浏览器窗口,即可完成安装 Firefox用户可以在 ...
- 利用tox打造自动自动化测试框架
什么是tox tox官方文档的第一句话 standardize testing in Python,意思就是说标准化python中的测试,那是不是很适合测试人员来使用呢,我们来看看他究竟是什么? 根据 ...
- Vue.js +pdf.js 处理响应pdf文件流数据,前端转图片预览不可下载
使用场景及原因 实际业务中,一些说明书或协议仅支持用户在线预览,为避免用户自行下载,并进行修改,引发纠纷,特将文件已文件流的形式,传给前端并转为图片显示,此时可能会有人问,为什么不直接在后端转图片,前 ...
- Kubernetes实战总结 - DevOps实现
一.概述 Git:一个开源的分布式版本控制系统,可以有效.高速地处理从很小到非常大的项目版本管理. Jenkins:一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作. M ...
- laravel 缓存相关常用操作
//----------设置缓存----------- //Cache::put($key,$val,$minutes); 如果$key已存在,则覆盖原有值 Cache::put('name', '张 ...