前言

接上文,继续学习后续章节。细心的同学已经发现,我整理的并不一定是作者讲的内容,更多是结合自己的理解,加以阐述,所以建议结合原文一起理解。

第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)的更多相关文章

  1. MySQL深入研究--学习总结(2)

    前言 接上文,继续学习后续章节. 第四章&第五章<深入浅出索引> 这两章节主要介绍的索引结构及其如何合理建立索引,但是我觉得讲的比较简单. 总结回顾下吧,其实在我之前的文章< ...

  2. MySQL深入研究--学习总结(5)

    前言 接上文,继续学习后续章节.细心的同学已经发现,我整理的并不一定是作者讲的内容,更多是结合自己的理解,加以阐述,所以建议结合原文一起理解. 第20章<幻读是什么,幻读有什么问题?> 先 ...

  3. MySQL深入研究--学习总结(1)

    前言 本文是笔者学习"林晓斌"老师的<MySQL实战45讲>过程中的,对知识点的总结归纳以及对问题的思考记录,课程18年11月就出了,当时连载形式,我就上班途中一边开车 ...

  4. MySQL深入研究--学习总结(3)

    前言 接上文,继续学习后续章节.细心的同学已经发现,我整理的并不一定是作者讲的内容,更多是结合自己的理解,加以阐述,所以建议结合原文一起理解. 第九章<普通索引和唯一索引,如何选择> 从查 ...

  5. 【转】手把手教你读取Android版微信和手Q的聊天记录(仅作技术研究学习)

    1.引言 特别说明:本文内容仅用于即时通讯技术研究和学习之用,请勿用于非法用途.如本文内容有不妥之处,请联系JackJiang进行处理!   我司有关部门为了获取黑产群的动态,有同事潜伏在大量的黑产群 ...

  6. 手把手教你读取Android版微信和手Q的聊天记录(仅作技术研究学习)

    1.引言 特别说明:本文内容仅用于即时通讯技术研究和学习之用,请勿用于非法用途.如本文内容有不妥之处,请联系JackJiang进行处理!   我司有关部门为了获取黑产群的动态,有同事潜伏在大量的黑产群 ...

  7. 13本热门书籍免费送!(Python、SpingBoot、Entity Framework、Ionic、MySQL、深度学习、小程序开发等)

    七月第一周,网易云社区联合清华大学出版社为大家送出13本数据分析以及移动开发的书籍(Python.SpingBoot.Entity Framework.Ionic.MySQL.深度学习.小程序开发等) ...

  8. MySQL 定时器EVENT学习

    原文:http://blog.csdn.net/lifuxiangcaohui/article/details/6583535 MySQL 定时器EVENT学习 MySQL从5.1开始支持event功 ...

  9. 《Mysql 公司职员学习篇》 第二章 小A的惊喜

          第二章 小A的惊喜  ---- 认识数据库 吃完饭后,小Y和小A回到了家里,并打开电脑开始学习Mysql. 小Y:"小A,你平时的Excell文件很多的情况下,怎么样存放Exce ...

随机推荐

  1. Educational Codeforces Round 91 (Rated for Div. 2) A. Three Indices (模拟)

    题意:有一长度为\(n\)的序列,问是否能找到\(a_{i}<a_{j},a_{j}>a_{k},(i<j<k)\),如果满足,输出其位置. 题解:直接暴力两头找即可,最坏复杂 ...

  2. CF1462-C. Unique Number

    题意: 给出一个数字x,让你找出一个由1到9这九个数字组成的数字,这个数字的每一位加起来等于x,并且1到9每个数字只能出现一次.若能找到这样的数字,输出这其中最小的一个,否则输出-1. 思路: 利用二 ...

  3. Spring Boot @Enable*注解源码解析及自定义@Enable*

      Spring Boot 一个重要的特点就是自动配置,约定大于配置,几乎所有组件使用其本身约定好的默认配置就可以使用,大大减轻配置的麻烦.其实现自动配置一个方式就是使用@Enable*注解,见其名知 ...

  4. C# 类 (11) - Const

    Const variable 变量 ,值可变的constant 常量,不可变,C# 里关键字是const当我们定义一个常量的时候,需要立马赋值,以后不能再改这个量了我们可以把常量定义在 method ...

  5. 使用 js 实现十大排序算法: 堆排序

    使用 js 实现十大排序算法: 堆排序 堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法. 大顶堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排列: 小顶堆:每个 ...

  6. 如何禁用 Chrome Taps Group feature &#128169;

    如何禁用 Chrome Taps Group feature bug https://support.google.com/chrome/go/feedback_confirmation How to ...

  7. LeetCode 算法题解 js 版 (001 Two Sum)

    LeetCode 算法题解 js 版 (001 Two Sum) 两数之和 https://leetcode.com/problems/two-sum/submissions/ https://lee ...

  8. js script all in one

    js script all in one 你不知道的 js secret https://html.spec.whatwg.org/multipage/scripting.html https://h ...

  9. JavaScript & Atomics

    JavaScript & Atomics Atomics 对象提供了一组静态方法对 SharedArrayBuffer 和 ArrayBuffer 对象进行原子操作. Atomics.add ...

  10. VSCode & SQL

    VSCode & SQL MySQL MySQL https://marketplace.visualstudio.com/items?itemName=formulahendry.vscod ...