常见面试题-MySQL专栏(一)

为什么 mysql 删了行记录,反而磁盘空间没有减少?

答:

在 mysql 中,当使用 delete 删除数据时,mysql 会将删除的数据标记为已删除,但是并不去磁盘上真正进行删除,而是在需要使用这片存储空间时,再将其从磁盘上清理掉,这是 MySQL 使用延迟清理的方式。

延迟清理的优点:

  • 如果 mysql 立即删除数据,会导致磁盘上产生大量的碎片,使用延迟清理可以减少磁盘碎片,提高磁盘的读写效率
  • 如果删除数据时立即清理磁盘上的数据,会消耗大量的性能。(如果一个大表存在索引,只删除其中一行,整个索引结构就会发生变化)

延迟清理的缺点:

  • 这些被标记为删除的数据,就是数据空洞,不仅浪费空间,还影响查询效率。
    mysql 是以数据页为单位来存储和读取数据,如果一个表有大量的数据空洞,那么 mysql 读取一个数据页,可能被标记删除的数据就占据了大量的空间,导致需要读取很多个数据页,影响查询效率

如何回收未使用空间:

optimize table 表名

索引的结构?

答:

索引是存储在引擎层而不是服务层,所以不同存储引擎的索引的工作方式也不同,我们只需要重点关注 InnoDB 存储引擎和 InnoDB 存储引擎中的索引实现,以下如果没有特殊说明,则都为 InnoDB 引擎。

mysql 支持两种索引结构: B-tree 和 HASH

  • B-tree 索引

B-tree 索引结构使用 B+ 树来进行实现,结构如下图(粉色区域存放索引数据,白色区域存放下一级磁盘文件地址):
请添加图片描述

B-tree 索引(B+ 树实现)的一些特点:

  • B+ 树叶子节点之间按索引数据的大小顺序建立了双向链表指针,适合按照范围查找
  • 使用 B+ 树非叶子节点只存储索引,在 B 树中,每个节点的索引和数据都在一起,因此使用 B+ 树时,通过一次磁盘 IO 拿到相同大小的存储页,B+ 树可以比 B 树拿到的索引更多,因此减少了磁盘 IO 的次数。
  • B+ 树查询性能更稳定,因为数据只保存在叶子节点,每次查询数据,磁盘 IO 的次数是稳定的

为什么索引能提高查询速度?

答:

索引可以让服务器快速定位到表的指定位置,索引有以下几个优点:

  • 索引大大减少了服务器需要扫描的数据量
  • 索引可以帮助服务器避免排序和临时表
  • 索引可以将随机 IO 变为顺序 IO

前缀索引和索引的选择性?

答:

索引的选择性:指的是不重复的索引值与数据表的记录总数的比值。

索引的选择性越高,查询效率也越高,因为选择性高的索引可以让 mysql 在查找时过滤掉更多的行。唯一索引的选择性是1,这也是最好的索引选择性,性能也是最好的

前缀索引:

有时候为了提高索引的性能,并且节省索引的空间,只对字段的前一部分字符进行索引,但是存在的缺点就是:降低了索引的选择性

如何选择前缀索引的长度呢?

前缀索引的长度选择我们要兼顾索引的选择性和存储索引的空间两个方面,因此既不能太长也不能太短,可以通过计算不同前缀索引长度的选择性,找到最接近完整列的选择性的前缀长度,通过以下 sql 进行计算不同前缀索引长度的选择性:

select 
count(distinct left(title, 6)) / count(*) as sel6,
count(distinct left(title, 7)) / count(*) as sel7,
count(distinct left(title, 8)) / count(*) as sel8,
count(distinct left(title, 9)) / count(*) as sel9,
count(distinct left(title, 10)) / count(*) as sel10,
count(distinct left(title, 11)) / count(*) as sel11,
count(distinct left(title, 12)) / count(*) as sel12,
count(distinct left(title, 13)) / count(*) as sel13,
count(distinct left(title, 14)) / count(*) as sel14,
count(distinct left(title, 15)) / count(*) as sel15,
count(distinct left(title, 16)) / count(*) as sel16,
count(distinct left(title, 17)) / count(*) as sel17,
count(distinct left(title, 18)) / count(*) as sel18,
count(distinct left(title, 19)) / count(*) as sel19,
count(distinct left(title, 20)) / count(*) as sel20,
count(distinct left(title, 21)) / count(*) as sel21
from interview_experience_article 

计算结果如下:
请添加图片描述

再计算完整列的选择性:

select count(distinct title)/count(*)  from interview_experience_article 

计算结果如下:

请添加图片描述

完整列的选择性是 0.6627,而前缀索引在长度为 16 的时候选择性为(sel16=0.6592),就已经很接近完整列的选择性了,此使再增加前缀索引的长度,选择性的提升幅度就已经很小了,因此在本例中,可以选择前缀索引长度为 16

本例中的数据是随便找的一些文本数据,类型是 text

如何创建前缀索引:

alter table table_name add key(title(16))

如何选择合适的索引顺序?

答:

来源于《高性能MySQL》(第4版)

对于选择合适的索引顺序来说,有一条重要的经验法则:将选择性最高的列放到索引的最前列

在通常境况下,这条法则会有所帮助,但是存在一些特殊情况:

对于下面这个查询语句来说:

select count(distinct threadId) as count_value
from message
where (groupId = 10137) and (userId = 1288826) and (anonymous = 0)
order by priority desc, modifiedDate desc

explain 的结果如下(只列出使用了哪个索引):

id: 1
key: ix_groupId_userId

可以看出选择了索引(groupId, userId),看起来比较合理,但是我们还没有考虑(groupId、userId)所匹配到的数据的行数:

select count(*), sum(groupId=10137), sum(userId=1288826), sum(anonymous=0)
from message

结果如下:

count(*): 4142217
sum(groupId=10137): 4092654
sum(userId=1288826): 1288496
sum(anonymous=0): 4141934

可以发现通过 groupId 和 userId 基本上没有筛选出来多少条数据

因此上边说的经验法则一般情况下都适用,但是在特殊形况下,可能会摧毁整个应用的性能

上边这种情况的出现是因为这些数据是从其他应用迁移过来的,迁移的时候把所有的消息都赋予了管理组的用户,因此导致这样查询出来的数据量非常大,这个案例的解决情况是修改应用程序的代码:区分这类特殊用户和组,禁止针对这类用户和组执行这个查询

聚簇索引和非聚簇索引的区别?非聚集索引一定回表查询吗?

答:

聚簇索引并不是一种单独的索引类型,而是一种数据存储方式。

当表里有聚簇索引时,它的数据行实际上存放在索引的叶子节点中。

聚簇表示数据行和相邻和键值存储在一起

InnoDB 根据主键来聚簇数据,如果没有定义主键的话,InnoDB 会隐式定义一个主键来作为聚簇索引,

聚簇索引的优点:

  • 数据访问更快。聚簇索引将数据和索引保存在同一个 B-tree 中,获取数据比非聚簇索引更快
  • 使用覆盖索引扫描的查询可以直接使用叶节点的主键值

聚簇索引的缺点:

  • 提升了 IO 密集型应用的性能。(如果数据全部放在内存中的话,不需要执行 IO 操作,聚集索引就没有什么优势了)
  • 插入速度严重依赖于插入顺序。按照主键的顺序插入行是将数据加载到 InnoDB 表中最快的方式。
    如果不是按照逐渐顺序加载数据,在加载完之后最好使用 optimize table 重新组织一下表,该操作会重建表。重建操作能更新索引统计数据并释放聚簇索引中的未使用的空间。
    可以使用show table status like '[table_name]'查看优化前后表占用的存储空间
  • 更新聚集索引的代价很高。因为会强制 InnoDB 将每个被更新的行移动到新的位置
  • 基于聚簇索引的表在插入新行是或者主键被更新到只需要移动行的时候,可能面临 页分裂 的问题,当行的主键值需要插入某个已经满了的页中时,存储引擎会将该页分裂成两个页面来存储,也就是页分裂操作,页分裂会导致表占用更多的磁盘空间
  • 聚簇索引可能会导致全表扫描变慢,尤其是行比较稀疏或者由于页分裂导致数据存储不连续的时候
  • 二级索引(也是非聚簇索引)可能比想象的要更大,因为在二级索引的叶子节点存储了指向行的主键列。
  • 二级索引访问需要两次索引查找,而不是一次。
    二级索引中,叶子节点保存的是指向行的主键值,那么如果通过二级索引进行查找,找到二级索引的叶子节点,会先获取对应数据的主键值,然后再根据这个值去聚簇索引中查找对应的行数据。(两次索引查找)

二级索引是什么?为什么已经有了聚集索引还需要使用二级索引?

答:

二级索引是非主键索引,也是非聚集索引(索引和数据分开存放),也就是在非主键的字段上创建的索引就是二级索引。

比如我们给一张表里的 name 字段加了一个索引,在插入数据的时候,就会重新创建一棵 B+ 树,在这棵 B+ 树中,就来存放 name 的二级索引。

即在二级索引中,索引是 name 值,数据(data)存放的是主键的值,第一次索引查找获取了主键值,之后根据主键值再去聚集索引中进行第二次查找,才可以找到对应的数据。

常见的二级索引:

  • 唯一索引
  • 普通索引
  • 前缀索引:只适用于字符串类型的字段,取字符串的前几位字符作为前缀索引。

为什么已经有了聚簇索引还需要使用二级索引?
聚簇索引的叶子节点存储了完整的数据,而二级索引只存储了主键值,因此二级索引更节省空间。

如果需要为表建立多个索引的话,都是用聚簇索引的话,将占用大量的存储空间。

为什么在 InnoDB 表中按逐渐顺序插入行速度更快呢?

答:

向表里插入数据,主键可以选择整数自增 ID 或者 UUID。

  • 如果选择自增 ID 作为主键

那么在向表中插入数据时,插入的每一条新数据都在上一条数据的后边,当达到页的最大填充因子(InnoDB 默认的最大填充因子是页大小的 15/16,留出部分空间用于以后修改)时,下一条记录就会被写入到新的页中。

  • 如果选择 UUID 作为主键

在插入数据时,由于新插入的数据的主键的不一定比之前的大,所以 InnoDB 需要为新插入的数据找到一个合适的位置——通常是已有数据的中间位置,有以下缺点:

  1. 写入的目标也可能已经刷到磁盘上并从内存中删除,或者还没有被加载到内存中,那么 InnoDB 在插入之前,需要先将目标页读取到内存中。这会导致大量随机 IO
  2. 写入数据是乱序的,所以 InnoDB 会频繁执行页分裂操作
  3. 由于频繁的页分裂,页会变得稀疏并且被不规则地填充,最终数据会有碎片

什么时候使用自增 ID 作为主键反而更糟?

在高并发地工作负载中,并发插入可能导致间隙锁竞争。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/108664.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

(速进)完美解决“用户在命令行上发出了 EULAS_AGREED=1,表示不接受许可协议。”以及“此产品安装程序不支持降级”

安装VMware时候,出现以下两种情况的原因是:未彻底卸载(之前安装过VMware),例如:还有相关配置信息、注册表信息等。只要彻底清理就可以解决此问题。 网上很多帖子使用了powershell里的命令 例如&#xff1…

基于 matplotlib 实现的基本排序算法的动态可视化项目源码,通过 pyaudio 增加音效,冒泡、选择、插入、快速等排序

基本排序算法动态可视化 依托 matplotlib 实现的基本排序算法的动态可视化,并通过 pyaudio 增加音效。 安装 在使用之前请先检查本地是否存在以下库: matplotlibpyaudiofire requirements.txt 中包含了上述的库 使用 目前本项目仅提供了以下排序算…

【Java网络原理】 六

本文主要介绍了网络层的IP协议/NAT机制/IPv6的由来以及在数据链路层涉及到的以太网协议和DNS域名解析系统 一.网络层 1.IP协议 各个字段所表示的含义 >4位版本号 用来表示IP协议的版本,现在只有两个版本IPv4 ,IPv6 >4位首部长度 IP报头可变&…

ZYNQ连载02-开发环境

ZYNQ连载02-开发环境 1. 官方文档 ZYNQ开发使用的软件为Vivado/Vitis/PetaLinux,软件体积比较大,硬盘保留100G以上的空间,赛灵思提供详细的文档,链接如下: ZYNQ文档 2. Vivido和Vitis安装 赛灵思统一安装程序 3. PetaLinux安装…

设计模式面试知识点总结

文章目录 设计原则常用设计模式单例模式1. 饿汉式2. 懒汉式3. 双重检测 工厂方法模式(简单工厂、工厂方法、抽象工厂)简单工厂静态工厂工厂方法模式抽象工厂模式 策略模式责任链模式 设计原则 标记设计模式原则名称简单定义OCP开闭原则对扩展开放&#…

VSCode 自动格式化

1.打开应用商店,搜索 prettier code formatter ,选择第一个,点击安装。 2.安装完成后,点击文件,选择首选项,选择设置。 3.在搜索框内输入 save ,勾选在保存时格式化文件。 4.随便打开一个文件&a…

【iOS】——知乎日报第二周总结

文章目录 一、自定义cell内容乱序问题二、WKWebView加载网页三、通过cell的协议函数进入指定网页四、滚动视图左滑加载新的网页五、隐藏导航栏 一、自定义cell内容乱序问题 当我下拉刷新的时候一开始我自定义的cell的内容顺序没有问题,当我一直下拉刷新或者上滑看以…

leetcode-链表

链表是一个用指针串联起来的线性结构,每个结点由数据域和指针域构成,指针域存放的是指向下一个节点的指针,最后一个节点指向NULL,第一个结点称为头节点head。 常见的链表有单链表、双向链表、循环链表。双向链表就是多了一个pre指…

ITSource 分享 第5期【校园信息墙系统】

项目介绍 本期给大家介绍一个 校园信息墙 系统,可以发布信息,表白墙,分享墙,校园二手买卖,咨询分享等墙信息。整个项目还是比较系统的,分为服务端,管理后台,用户Web端,小…

ELASTICO-A Secure Sharding Protocol For Open Blockchains

INTRO 在中本聪共识中,通过POW机制来公平的选举leader,不仅非常消耗power,并且拓展性也不好。现在比特币中是7 TPS,和其他的支付系统相比效率相差甚远。 当前的许多拜占庭共识协议,并不支持在一个开放的环境中使用&a…

C语言实现输入一个字符串,递归将其逆序输出

完整代码&#xff1a; // 输入一个字符串&#xff0c;递归将其逆序输出。如输入 LIGHT&#xff0c;则输出 THGIL #include<stdio.h> #include<stdlib.h> //字符串的最大长度 #define N 20//逆序输出字符串 void func(char *str){if (*str\0){//结尾时直接退出递归…

Java SE 学习笔记(十七)—— 单元测试、反射

目录 1 单元测试1.1 单元测试概述1.2 单元测试快速入门1.3 JUnit 常用注解 2 反射2.1 反射概述2.2 获取类对象2.3 获取构造器对象2.4 获取成员变量对象2.5 获取常用方法对象2.6 反射的作用2.6.1 绕过编译阶段为集合添加数据2.6.2 通用框架的底层原理 1 单元测试 1.1 单元测试概…

基于单片机的太阳跟踪系统的设计

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 技术交流认准下方 CSDN 官方提供的联系方式 文章目录 概要 一、设计的主要内容二、硬件电路设计2.1跟踪控制方案的选择2.1.1跟踪系统坐标系的选择2.2系统总体设计及相关硬件介绍…

服务熔断保护实践--Hystrix

概述 微服务有很多互相调用的服务&#xff0c;构成一系列的调用链路&#xff0c;如果调用链路中某个服务失效或者网络堵塞等问题&#xff0c;而有较多请求都需要调用有问题的服务时&#xff0c;这是就会造成多个服务的大面积失效&#xff0c;造成服务“雪崩”效应。 服务“雪…

十九、类型信息(2)

本章概要 Class 对象 类字面常量泛化的 Class 引用cast() 方法 Class 对象 要理解 RTTI 在 Java 中的工作原理&#xff0c;首先必须知道类型信息在运行时是如何表示的。这项工作是由称为 **Class**对象 的特殊对象完成的&#xff0c;它包含了与类有关的信息。实际上&#x…

JVM第二十三讲:Java动态调试技术原理

Java动态调试技术原理 本文是JVM第二十三讲&#xff0c;Java动态调试技术原理。转载自 美团技术团队胡健的Java 动态调试技术原理及实践&#xff0c;通过学习java agent方式进行动态调试&#xff0c;了解目前很多大厂开源的一些基于此的调试工具 (例如来自阿里开源的Arthas)。 …

微信小程序设计之主体文件app-wxss/less

一、新建一个项目 首先&#xff0c;下载微信小程序开发工具&#xff0c;具体下载方式可以参考文章《微信小程序开发者工具下载》。 然后&#xff0c;注册小程序账号&#xff0c;具体注册方法&#xff0c;可以参考文章《微信小程序个人账号申请和配置详细教程》。 在得到了测…

elementUI 特定分辨率(如1920*1080)下el-row未超出一行却换行

在1920*1080分辨率下&#xff0c; el-col 内容未超出 el-col 宽度&#xff0c;el-col 不足以占据一行&#xff0c;el-row 却自动换行了&#xff08;其他分辨率没有这个问题&#xff09;。 截图&#xff1a; 排查&#xff1a; el-col 内容没有溢出&#xff1b;没有多余的 pad…

拜耳阵列(Bayer Pattern)和解马赛克简介

拜尔阵列 典型的图像传感器&#xff08;例如我们在数码相机中使用的图像传感器&#xff0c;主要有CCD, CMOS&#xff09;由许多单独的光电传感器组成&#xff0c;所有这些传感器都会捕获光线。这些光电传感器本身能够捕获光的强度&#xff0c;但不能捕获其波长&#xff08;颜色…

CTF-Web(3)文件上传漏洞

笔记目录 CTF-Web(2)SQL注入CTF-Web(3)文件上传漏洞 1.WebShell介绍 (1)一句话木马定义 一种网页后门&#xff0c;以asp、php、jsp等网页文件形式存在的一种命令执行环境&#xff0c;而 一句话木马往往只有一行WebShell代码。 作用&#xff1a; 攻击获得网站控制权限 查看、修改…