迎面走来了你的面试官,身穿格子衫,挺着啤酒肚,发际线严重后移的中年男子。

手拿泡着枸杞的保温杯,胳膊夹着MacBook,MacBook上还贴着公司标语:“加班使我快乐”。

面试官: 看你简历上用过MySQL,问你几个简单的问题吧。什么是聚簇索引和非聚簇索引?

这个问题难不住我啊。来之前我看一下一灯MySQL八股文。

我: 举个例子:有这么一张用户表

CREATE TABLE `user` (
`id` int COMMENT '主键ID',
`name` varchar(10) COMMENT '姓名',
`age` int COMMENT '年龄',
PRIMARY KEY (`id`)
) ENGINE=InnoDB CHARSET=utf8 COMMENT='用户表';

用户表中存储了这些数据:

id nane age
1 一灯 18
2 张三 22
3 李四 21
4 王二 19
5 麻子 20

那么在索引中,这些数据是怎么存储的呢?

MySQL的InnoDB引擎中索引使用的B+树结构。

别问为什么根节点存储了(1,4)两个元素,左子节点又存储了(1,2,3)三个元素,下面带有三个叶子节点,叶子节点之间又用有序链表相连?

问就是B+树的特性,不了解的可以翻一下上期的文章。

如上图所示,叶子节点中存储了全部元素的索引,就是聚簇索引

一般主键索引就是聚簇索引,如果表中没有主键,MySQL也会默认建立一个隐藏主键做主键索引。

什么是非聚簇索引?

假设我们在age(年龄)字段上建一个普通索引,age字段上面的索引存储结构就是下面这样:

叶子节点中只存储了当前索引字段和主键ID,这样的存储结构就是非聚簇索引。

面试官: 那什么是联合索引呢?

我: 有多个字段组成的索引就是联合索引。

面试官: 【晕】建联合索引有什么好处?它跟在单个字段上建索引有什么区别?

我: 假设有这么一条查询语句。

select * from user where age = 18 and name = '张三';

如果我们在age和name字段上分别建两个索引,这个查询语句只会用到其中一个索引。

但是我们在age和name字段建一个联合索引(age,name),它的存储结构就变成这样了。

如果只在age上面建索引,会先查询age上面非聚簇索引,有三条age=18的记录,主键ID分别是1、4、5,然后再用这三个ID去查询主键ID的聚簇索引。

如果在age和name上面建联合索引,会先查询age和name上面的非聚簇索引,匹配到一条记录,主键ID是1,然后再用这个ID去查询主键ID的聚簇索引。

由此可以得出,联合索引的优点:大大减少扫描行数。

面试官: 你再说一下什么是最左匹配原则?

我: 最左匹配原则是指在建立联合索引的时候,遵循最左优先,以最左边的为起点任何连续的索引都能匹配上。

当我们在(age,name)上建立联合索引的时候,where条件中只有age可以用到索引,同时有age和name也可以用到索引。但是只有name的时候是无法用到索引的。

为什么会出现这种情况呢?

看上面的图,就理解了,(age,name)的联合索引,是先按照age排序,age相等的行再按照name排序。如果where条件只有一个name,当然无法用到索引。

面试官: 什么是覆盖索引和回表查询?

我: 这个就更简单了,上面已经提到这个知识点了。

当我们在age上建索引的时候,查询SQL是这样的时候:

select id from user where age = 18;

就会用到覆盖索引,因为ID字段我们使用age索引的时候已经查出来,不需要再二次回表查询了。

但是当查询SQL是这样的时候:

select * from user where age = 18;

想要查询所有字段,就需要二次回表查询。因为我们第一次用age索引的时候只查出来了主键ID,还需要再用主键ID回表查询出所有字段。

面试官: 再问一个,你知道什么是索引下推吗?

这么冷门的问题,你都问的出来,真的要面试造火箭啊!

我: 索引下推(Index Condition Pushdown)是MySQL5.6引入的一个优化索引的特性。

举例:

在(age,name)上面建联合索引,并且查询SQL是这样的时候:

select * from user where age = 18 and name = '张三';

如果没有索引下推,会先匹配出 age = 18 的三条记录,再用ID回表查询,筛选出 name = '张三' 的记录。

如果使用索引下推,会先匹配出 age = 18 的三条记录,再筛选出 name = '张三' 的一条记录,最后再用ID回表查询。

由此得出,索引下推的优点:减少了回表的扫描行数。

**面试官: ** 小伙子,八股文背的挺溜啊。我给你出个实战题,看你有没有准备。下面这个查询SQL该怎么建联合索引?

select a from table where b = 1 and c = 2;

故意刁难我?你以为实战题就不能背八股文了吗?

我: 刚才在讲联合索引的时候已经说了这个知识点了,where条件有b和c的等值查询,联合索引就建成(b,c),由于select后面有a,我们就建立 (b,c,a) 的联合索引,并且可以用到覆盖索引,查询速度更快。

面试官: 小伙子,有点东西。一会儿就给你发offer,明天就来上班,薪资double。

文章持续更新,可以微信搜一搜「 一灯架构 」第一时间阅读更多技术干货。

一篇文章讲清楚MySQL的聚簇/联合/覆盖索引、回表、索引下推的更多相关文章

  1. 还分不清 Cookie、Session、Token、JWT?一篇文章讲清楚

    还分不清 Cookie.Session.Token.JWT?一篇文章讲清楚 转载来源 公众号:前端加加 作者:秋天不落叶 什么是认证(Authentication) 通俗地讲就是验证当前用户的身份,证 ...

  2. 聚簇(或者叫做聚集,cluster)索引和非聚簇索引

    字典的拼音目录就是聚簇(cluster)索引,笔画目录就是非聚簇索引.这样查询“G到M的汉字”就非常快,而查询“6划到8划的字”则慢. 聚簇索引是一种特殊索引,它使数据按照索引的排序顺序存放表中.聚簇 ...

  3. 【mysql】索引 回表 覆盖索引 索引下推

    索引类型 索引类型分为主键索引和非主键索引.(一定要牢记,是怎么存储数据的) 主键索引的叶子节点存的是整行数据.在 InnoDB 里,主键索引也被称为聚簇索引(clustered index). 非主 ...

  4. 一篇文章讲清楚android ImageView.ScaleType

    2016-01-10 刚开始android编程的时候, 关于ImageView.ScaleType网络上好多, 说实话没看懂. 本文就是为了讲清楚这个, 有用的话转走, 请注明原地址和作者. 典型的代 ...

  5. Oracle索引梳理系列(九)- 浅谈聚簇因子对索引使用的影响及优化方法

    版权声明:本文发布于http://www.cnblogs.com/yumiko/,版权由Yumiko_sunny所有,欢迎转载.转载时,请在文章明显位置注明原文链接.若在未经作者同意的情况下,将本文内 ...

  6. 聚集索引、非聚集索引、聚集索引组织表、堆组织表、Mysql/PostgreSQL对比、联合主键/自增长、InnoDB/MyISAM(引擎方面另开一篇)

    参考了多篇文章,分别记录,如下. 下面是第一篇的总结 http://www.jb51.net/article/76007.htm: 在MySQL中,InnoDB引擎表是(聚集)索引组织表(cluste ...

  7. oracle聚簇表的理解 (转自:https://blog.csdn.net/gumengkai/article/details/51009345 )

    Oracle支持两种类型的聚簇:索引聚簇和哈希聚簇 一.索引聚簇表的原理 聚簇:如果一些表有一些共同的列,则将这样一组表存储在相同的数据块中 聚簇还表示把相关的数据存储在同一个块上.利用聚簇,一个块可 ...

  8. oracle 索引聚簇表的工作原理

    作者:Richard-Lui 一:首先介绍一下索引聚簇表的工作原理:(先创建簇,再在簇里创建索引,创建表时指定列的簇类型) 聚簇是指:如果一组表有一些共同的列,则将这样一组表存储在相同的数据库块中:聚 ...

  9. 详细介绍Oracle数据库的聚簇技术

    作者:☜ Tracy ☞ 1. 什么是聚簇 d1=A=: 聚簇是根据码值找到数据的物理存储位置,从而达到快速检索数据的目的.聚簇索引的顺序就是数据的物理存储顺序,叶节点就是数据节点.非聚簇索引的顺序与 ...

随机推荐

  1. Blazor Bootstrap 组件库语音组件介绍

    Speech 语音识别与合成 通过麦克风语音采集转换为文字(STT),或者通过文字通过语音朗读出来(TTS) 本组件依赖于 BootstrapBlazor.AzureSpeech,使用本组件时需要引用 ...

  2. 条件表达式和switch语句

    一,条件表达式相当于(相当于if-else) 1.条件表达式 ? : 由条件运算符组成条件表达式的一般情况为: 表达式1?表达式2:表达式3: 求值规则:如果表达式的值为真,则以表达式2的值作为条件的 ...

  3. 《Mybatis 手撸专栏》第6章:数据源池化技术实现

    作者:小傅哥 博客:https://bugstack.cn - 手写Mybatis系列文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 码农,只会做不会说? 你有发现吗,其实很大一部分码农 ...

  4. XCTF练习题---MISC---再见李华

    XCTF练习题---MISC---再见李华 flag:Stay hungry, Stay foolish. 解题步骤: 1.观察题目,下载附件 2.拿到手以后发现是一张图片,其中有MD5,破解一下没有 ...

  5. 跨域原因及SpringBoot、Nginx跨域配置

    目录 概述 简单请求 跨域解决方案 概述 SpringBoot跨域配置 Nginx跨域配置 概述 MDN文档 Cross-Origin Resource Sharing (CORS) 跨域的英文是Cr ...

  6. 实战 | Linux根分区扩容

    一个执着于技术的公众号 一个执着于技术的公众号 前言 Linux系统作为服务器操作系统,经常遇到一个问题就是服务器分区磁盘空间不足需要扩容的情况.本文以linux系统最常见的发行版centos7系统为 ...

  7. 使用 Swoole 加速你的 CMS 系统,并实现热更新 (基于 Laravel 框架)

    主题:使用 Swoole 加速你的 CMS 系统,并实现热更新 关于 Swoole 的简介不再在此赘述,各位可以自行查看官网的文档进行详细的了解. 本文以 MyCms 为例,简要说明 Swoole 结 ...

  8. dnf常用参数

    dnf常用命令 检查并升级可用软件包: $ dnf update 删除缓存: $dnf clean all 列出可用的软件源: $ dnf repolist 搜索软件: $ dnf search $p ...

  9. Vue组件之间通信

    vue组件传值有以下几种情况: 父组件向子组件传值.子组件向父组件传值.兄弟组件之间传值等 一.父组件向子组件传值: 传值方式: props <father> // 动态传递值 <s ...

  10. C# WPF后台动态添加控件(经典)

    概述 在Winform中从后台添加控件相对比较容易,但是在WPF中,我们知道界面是通过XAML编写的,如何把后台写好的控件动态添加到前台呢?本节举例介绍这个问题. 这里要用到UniformGrid布局 ...