MySQL深入研究--学习总结(4)
前言
接上文,继续学习后续章节。细心的同学已经发现,我整理的并不一定是作者讲的内容,更多是结合自己的理解,加以阐述,所以建议结合原文一起理解。
第13章《为什么表数据删除一般,表文件大小不变?》
我们在知道MySQL表的存储,在8.0之前的版本,表结构相关数据存在.frm文件中,表数据存在.ibd文件中。可以通过innoDB_file_per_table控制,OFF表示表数据页放在系统共享表空间,这时候删除表数据,文件大小也不会变。
但即使,表数据单独存在.ibd文件中,当我们通过delete删除时,发现文件大小也不会变。
这是因为表数据在B+结构中,当我们删除一条数据时,并不会真把这个数据给彻底删除,只是在这个位置上做个删除的标记。被标记删除的位置,可以被复用,等待下次有数据插入时,可以保存在该位置,但实际文件大小不会表的。不仅删除,插入也是如此,当插入时,出现也分裂,就可能出现空洞。也就是说一个表经过大量的增删改,就会出现大量的空洞。所以我们会发现但我们删除表数据,文件大小也不会表。
那么如何解决这个问题,把表压缩下呢?
可以通过:重建表
这里,你可以使用alter table A engine=innoDB命令来重建表。
在5.5版本版本之前,这个命令做了如下几个操作:
1、新建一个与表A一样结构的表B。
2、将表A的数据按ID自增的顺序写入表B。
但是在这个过程中,增删改是会丢失的。
所以在5.6版本之后,引入了Online DDL。
1、新增一个临时文件,扫描A主键的所有数据页。
2、根据数据页中表A的记录生成B+树,存储到临时文件。
3、在生成过程中,将对A的所有更新操作,记录在row log 文件中。
4、临时文件生成完毕后,将row log中的数据,维护到临时文件中,然后用临时文件替代表A的数据文件。
第14章 《count(*)特别慢,怎么办?》
当一张数据量很大的表,比如一张1千万数据量的表,做count(*)时,很慢这是什么原因呢?
首先我们要从存储引擎区分,在MyISAM中,count(*)的结果记录在文件中,所以会直接返回。
而innoDB中,count(*)时,需要一行一行扫描统计行数。所以当数据量很大时,就会变的很慢。
那为什么innoDB不跟MyISAM一样呢,这是因为MyISAM是不支持事务的。而在innoDB中,同一时刻,由于可重复读的隔离级别特性,不同事务做统计查询,查询的结果可能是不一样的。
所以不能直接用一个统计给所有事务通用。
那业务上我们的确需要统计全表的数量,怎么办?
1、把count(*)的数据保存在Redis中,每当插入删除时,更新缓存,但这不适用于带where条件的查询。
2、把count(*)的数值存在mysql表中。
优缺点:
如果把统计数据放在Redis,在单机器下,宕机就没法用了,虽然可以通过集群来达到高可用。当数据库的操作与Redis的操作,存在数据一致性的问题。比如既要返回count数据,又要返回最新的100条数据,就可能出现最新的数据不一定在count统计中,或者统计了最新的数据,但并不在表中,想一想这是为什么?
所以建议,如果对count的实时性不是特别高的时候,可以使用该方案。
正因为有Redis和MySQL没法同时支持分布式事务,如果把count数据存在MySQL表中,通过事务就可以解决这样的问题,但显然两次表操作也是缺点所在。
count(*) 、count(1) 、count(id)、 count(字段)不同方式有什么区别?
count(*)和count(1)都是只统计行数,不返回数据,性能最优,MySQL官方也说明了两者本质没有区别。
count(id)扫描所有id,再统计行数,多了id字段的返回,索引性能比count(*)和count(1)略差.
count(字段)扫描该字段并返回,如果该字段允许为null.就得统计不为null的数据,所以比count(id)性能差。
第16章《order by是如何工作的?》
背景条件:
有这样一张表
CREATE TABLE `t` (
`id` int(11) NOT NULL,
`city` varchar(16) NOT NULL,
`name` varchar(16) NOT NULL,
`age` int(11) NOT NULL,
`addr` varchar(128) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `city` (`city`)
) ENGINE=InnoDB;
--执行这样的一个查询语句,MySQL是怎么工作的呢?
select city,name,age from t where city='杭州' order by name limit 1000;
1、首先根据辅助索引查询出city="杭州"的数据。
2、发现第一个city=“杭州”数据时,得到对应的id,再根据id去主键索引中查出该行的完整数据。
3、查询得到完整数据后,取city,name,age三个字段,放入sort buffer中。
4、重复上述动作,查询出索引city=“杭州”的数据。
5、将sort buffer中的数据,按name排序,取出前1000条并返回。查询结果。
这个称为全字段排序。
几个概念:
sort buffer:MySQL为了排序的高效,为每个线程会在内存中开辟一块内存,专门用于排序。
sort buffer size:决定了排序缓冲区的大小,超过排序缓冲区的数据,便只能使用额外的文件用于排序。
max_length_for_sort_data:限定用于排序时,单行数据的大小,超过这个大小的行,就会使用另外一个排序方法,如下。
几个疑问:
如果单行的数据很大,sort buffer中可存放的数据就少了,那么就要分成很多临时文件(归并排序),排序的性能就会很低,怎么办?
MySQL发现当行数据的大小超过设置的max_length_for_sort_data时,就会采用另外一种算法,整个排序过程如下:
1、首先根据辅助索引查询出city="杭州"的数据。
2、发现第一个city=“杭州”数据时,得到对应的id,再根据id去主键索引中查出该行的完整数据。
3、查询得到完整数据后,取id,name两个字段,放入sort buffer中。
4、重复上述动作,查询出索引city=“杭州”的数据。
5、将sort buffer中的数据,按name排序,取出前1000条。
6、再根据sort buffer中name与id的对应关系,根据id再回表遍历查询出整行数据,取name,city,age三个字段返回给客户端。
我们会发现比第一种方法,多了一次回表查询。这个成为rowid排序。
第18章《为什么这些SQL语句逻辑相同,性能却差异巨大?》
主要讲了三个场景,其实SQL优化的核心就是,能不能用到索引,能不能减少回表查询,能不能使用到覆盖索引,本质就是以空间换时间。
场景一:条件字段做函数操作
当一个查询语句的where条件字段做了函数操作,是无法走索引的,比如where id +1 =2;
本质上就是因为MySQL无法判断该字段函数操作后不再有序了,只能全索引扫描。
场景二:隐式类型转换
就是类型转换,比如原本字段是varchar,缺没有带“”查询,就会针对这个字段做类型转换函数,MySQL发现字符类型和数值类型比较时,会把字符串转换成数值。
显然当一个查询语句的where条件字段做了函数操作,是无法走索引的。
场景三:隐式字符编码转换
当两个表关联查询,关联条件的两个字段,字符集编码不一致时,也需要进行函数转换,同样的也不会走索引。
MySQL深入研究--学习总结(4)的更多相关文章
- MySQL深入研究--学习总结(2)
前言 接上文,继续学习后续章节. 第四章&第五章<深入浅出索引> 这两章节主要介绍的索引结构及其如何合理建立索引,但是我觉得讲的比较简单. 总结回顾下吧,其实在我之前的文章< ...
- MySQL深入研究--学习总结(5)
前言 接上文,继续学习后续章节.细心的同学已经发现,我整理的并不一定是作者讲的内容,更多是结合自己的理解,加以阐述,所以建议结合原文一起理解. 第20章<幻读是什么,幻读有什么问题?> 先 ...
- MySQL深入研究--学习总结(1)
前言 本文是笔者学习"林晓斌"老师的<MySQL实战45讲>过程中的,对知识点的总结归纳以及对问题的思考记录,课程18年11月就出了,当时连载形式,我就上班途中一边开车 ...
- MySQL深入研究--学习总结(3)
前言 接上文,继续学习后续章节.细心的同学已经发现,我整理的并不一定是作者讲的内容,更多是结合自己的理解,加以阐述,所以建议结合原文一起理解. 第九章<普通索引和唯一索引,如何选择> 从查 ...
- 【转】手把手教你读取Android版微信和手Q的聊天记录(仅作技术研究学习)
1.引言 特别说明:本文内容仅用于即时通讯技术研究和学习之用,请勿用于非法用途.如本文内容有不妥之处,请联系JackJiang进行处理! 我司有关部门为了获取黑产群的动态,有同事潜伏在大量的黑产群 ...
- 手把手教你读取Android版微信和手Q的聊天记录(仅作技术研究学习)
1.引言 特别说明:本文内容仅用于即时通讯技术研究和学习之用,请勿用于非法用途.如本文内容有不妥之处,请联系JackJiang进行处理! 我司有关部门为了获取黑产群的动态,有同事潜伏在大量的黑产群 ...
- 13本热门书籍免费送!(Python、SpingBoot、Entity Framework、Ionic、MySQL、深度学习、小程序开发等)
七月第一周,网易云社区联合清华大学出版社为大家送出13本数据分析以及移动开发的书籍(Python.SpingBoot.Entity Framework.Ionic.MySQL.深度学习.小程序开发等) ...
- MySQL 定时器EVENT学习
原文:http://blog.csdn.net/lifuxiangcaohui/article/details/6583535 MySQL 定时器EVENT学习 MySQL从5.1开始支持event功 ...
- 《Mysql 公司职员学习篇》 第二章 小A的惊喜
第二章 小A的惊喜 ---- 认识数据库 吃完饭后,小Y和小A回到了家里,并打开电脑开始学习Mysql. 小Y:"小A,你平时的Excell文件很多的情况下,怎么样存放Exce ...
随机推荐
- linux搭建网站
CentOS 1.安装 yum -y install nginx *或者安装指定版本,版本网址:http://nginx.org/packages/centos/7/x86_64/RPMS/ rpm ...
- Docker网络模式详解
一.Docker四种工作模式 安装Docker时,它会自动创建三个网络,bridge(创建容器默认连接到此网络). none .hosthost:容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用 ...
- Pod 实现机制
Pod 为了亲密性应用而存在: 两个应用需要通过 127.0.0.1 或者 Socket 通信: 两个应用之间发生文件交互: 两个应用发生频繁的调用 共享网络 Pod 中的所有容器拥有同一个 IP 地 ...
- vagrant + virtualbox安装centos环境+docker安装
1. 下载vagrant 并安装,安装完成后,输入vagrant回车查看是否安装成功 2. 下载virtualbox.box并安装,安装完成后. 3. 创建虚拟机文件夹,例如.F:/vmimg/fir ...
- vue中怎么动态生成form表单
form-create 是一个可以通过 JSON 生成具有动态渲染.数据收集.验证和提交功能的表单生成组件.支持3个UI框架,并且支持生成任何 Vue 组件.内置20种常用表单组件和自定义组件,再复杂 ...
- jira 优先级过滤
jira 优先级过滤 priority project = DAP AND issuetype = 故障 AND priority = high AND resolution = Unresolved ...
- Nginx环境下,PHP下载,中文文件,下载失效(英文可以下载)怎么解决呢?
参考出处: http://www.imooc.com/qadetail/76393 Nginx环境下,PHP下载,中文文件,下载失效(英文可以下载)怎么解决呢? 背景介绍: 文件名 为英文时可以下载 ...
- Get your site working on Google Search Console , 在 Google Search Console中运行您的网站, Google Search Console
1 1 https://support.google.com/webmasters/topic/4564315? Search Console Help SEARCH CONSOLEHELP FORU ...
- Taro 开发踩坑指南 (小程序,H5, RN)
Taro 开发踩坑指南 (小程序,H5, RN) css taro 如何展示多行文本省略号 https://www.cnblogs.com/xgqfrms/p/12569057.html UI 设计稿 ...
- nodejs 显示进度条插件
ora 显示loading.. progress 进度条 progress var ProgressBar = require("progress"); var bar = new ...