Skip to content

Commit

Permalink
update sql docs
Browse files Browse the repository at this point in the history
  • Loading branch information
fengzhao committed Oct 19, 2023
1 parent 7345608 commit 8570fdd
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 8 deletions.
15 changes: 15 additions & 0 deletions docs/basic/4.sql.md
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,21 @@ where col_name in (value1, value2,...);
-- in 查询就是先将子查询条件的记录全都查出来。
-- in 查询的子条件返回结果必须只有一个字段。


-- 查找拥有员工的部门
SELECT *
FROM department d
WHERE EXISTS (SELECT 1 FROM employee WHERE dept_id = d.dept_id);


SELECT *
FROM department d
WHERE dept_id IN (SELECT dept_id FROM employee);

SELECT *
FROM department d
WHERE dept_id = ANY (SELECT dept_id FROM employee);

```


Expand Down
63 changes: 55 additions & 8 deletions docs/basic/9.mysql_architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ MySQL请求处理流程
4. MySQL根据执行计划,调用存储引擎的API来执行查询。
5. 将结果返回给客户端,同时缓存查询结果。

每一个客户端发起一个新的请求都由服务器端的 **连接/线程处理工具** 负责接收客户端的请求并开辟一个新的内存空间,在服务器端的内存中生成一个新的线程
每一个客户端发起一个新的请求都由服务器端的 **连接/线程处理工具** 负责接收客户端的请求,并在服务端内存中开辟一个新的内存空间,生成一个新的线程

当每一个用户连接到服务器端的时候就会在进程地址空间里生成一个新的线程用于响应客户端请求,用户发起的查询请求都在线程空间内运行,结果也在这里面缓存并返回给服务器端。

Expand Down Expand Up @@ -51,6 +51,15 @@ MySQL客户端/服务端 **通信协议是“半双工”的:在任一时刻
# max_allowed_packet表示服务器所能处理的请求包的最大值。默认是64MB,最大值是1GB。MySQL 8.0单个packet可以允许的最大值是1GB
# 客户端和服务端都有自己的max_allowed_packet变量,所以要调节此参数时,必须同时增加server端和client端的配置变量。
max_allowed_packet=64MB


# 每个客户端线程都关联了 1 个连接缓冲区(connection buffer)和 1 个结果集缓冲区(result buffer)。
# 这 2 个缓冲区的初始大小都由 net_buffer_length 控制,需要时最大可以自动增长到不超过 max_allowed_packet。
# 每条 SQL 语句执行完成后,结果集缓冲区都会自动恢复到 net_buffer_length 指定的大小。

# 一般情况下,不应该修改 net_buffer_length 的值,如果这个值设置得非常小,你可以把它修改为客户端发送的 SQL 语句预期的长度。
# 如果 SQL 语句长度超过这个值,连接缓冲区还会自动增长。net_buffer_length 的最大值为 1048576(1M)。

```

MySQL是C/S结构,client与server之间的通信需要遵循约定的规则,C/S之间通信的最小单元就是packet,通信约定的规则就是packet的结构。
Expand All @@ -68,7 +77,7 @@ MySQL是C/S结构,client与server之间的通信需要遵循约定的规则,

与之相反的是,服务器响应给用户的数据通常会很多,由多个数据包组成。当服务器响应客户端请求时,客户端必须完整的接收整个返回结果,而不能简单的只取前面几条结果,然后让服务器停止发送。

这种情况下, 客户端若接收完整的结果, 然后取前面几条需要的结果, 或者接收完几条结果后就"粗暴"地断开连接,都不是好主意。
这种情况下,客户端若接收完整的结果,然后取前面几条需要的结果,或者接收完几条结果后就"粗暴"地断开连接,都不是好主意。

因而在实际开发中,**尽量保持查询简单且只返回必需的数据,减小通信间数据包的大小和数量是一个非常好的习惯**

Expand All @@ -77,7 +86,7 @@ MySQL是C/S结构,client与server之间的通信需要遵循约定的规则,
>> 引自《高性能 MySQL》。

当客户端从服务器取数据时, 看起来是一个拉数据的过程, 但实际上是 MySQL 在向客户端推送数据的过程。 客户端不断地接收从服务器推送的数据, 客户端也没法让服务器停下来。
当客户端从服务器取数据时,看起来是一个拉数据的过程,但实际上是 MySQL 在向客户端推送数据的过程。客户端不断地接收从服务器推送的数据,客户端也没法让服务器停下来。



Expand All @@ -95,9 +104,9 @@ InnoDB的数据是保存在主键索引上的,所以全表扫描实际上是

一个查询在发送过程中,占用的MySQL内部的内存最大就是net_buffer_length这么大,并不会达到200G;

socket send buffer 也不可能达到200G(默认定义/proc/sys/net/core/wmem_default),如果**socket send buffer**被写满,就会暂停读数据的流程。
socket send buffer 也不可能达到200G(默认定义/proc/sys/net/core/wmem_default),如果 **socket send buffer** 被写满,就会暂停读数据的流程。

也就是说,MySQL 是**边读边发的**,这个概念很重要。这就意味着,如果客户端接收得慢,会导致MySQL服务端由于结果发不出去,这个事务的执行时间变长。
也就是说,MySQL 是 **边读边发的**,这个概念很重要。这就意味着,如果客户端接收得慢,会导致MySQL服务端由于结果发不出去,这个事务的执行时间变长。



Expand Down Expand Up @@ -129,11 +138,11 @@ select * from information_schema.plugins -- where plugin_name like "%daemon%";

在完成TCP三次握手之后,连接器就要开始认证身份进行账密校验,校验通过之后,**连接器会到权限表里查询拥有的权限之后在这个连接里的权限判断,SQL执行的权限都依赖于此时读取的权限。**

这就意味着,一个用户成功建立连接后,即使你用管理员账号对这个用户的权限做了修改,也不会影响已经存在连接的权限。修改完成后,**有再新建的连接才会使用新的权限设置**
这就意味着,一个用户成功建立连接后,即使你用管理员账号对这个用户的权限做了修改,也不会影响已经存在连接的权限。修改完成后,**只有再新建的连接才会使用新的权限设置**

#### MySQL连接线程模型

MySQL是一个**单进程多线程**的软件,启动一个 MySQL 实例,操作系统中会使用 mysqld 这个可执行文件来启动一个mysqld进程。
MySQL是一个 **单进程多线程** 的软件,启动一个 MySQL 实例,操作系统中会使用 mysqld 这个可执行文件来启动一个mysqld进程。

mysqld 通过创建多个线程来服务于不同的用户连接。通常情况下,随着用户连接数的增加,MySQL内部用于处理用户连接的线程也会同步的增加,在一定范围内,增加用户并发连接,对提高系统的吞吐量有一定的帮助,然而用户并发连接数超过某个阈值,MySQL的性能反而会降低。

Expand Down Expand Up @@ -678,6 +687,44 @@ ALTER TABLE table2 Engine=InnoDB, STATS_PERSISTENT = (1|0);
1. 不改变语义的情况下,重写sql。重写后的 sql 更简单,更方便制定执行计划。
2. 根据成本分析,制定执行计划。

```sql
SELECT @@optimizer_switch;

index_merge=on,
index_merge_union=on,
index_merge_sort_union=on,
index_merge_intersection=on,
engine_condition_pushdown=on
index_condition_pushdown=on,
mrr=on,
mrr_cost_based=on,
block_nested_loop=on,
batched_key_access=off,
materialization=on,
semijoin=on,
loosescan=on,
firstmatch=on,
duplicateweedout=on,
subquery_materialization_cost_based=on,
use_index_extensions=on,
condition_fanout_filter=on,
derived_merge=on,
use_invisible_indexes=off,
skip_scan=on,
hash_join=on


-- 修改优化器
SET [GLOBAL|SESSION] optimizer_switch='command[,command]...';

-- command语法如下:
-- default --重置为默认
-- opt_name=default --选项默认
-- opt_name=off --关掉某项优化
-- opt_name=on --开启某项优化

```


举个例子,数据库中有个概念叫**谓词下推**

Expand Down Expand Up @@ -858,7 +905,7 @@ SELECT * FROM t1 WHERE t1.a IN (SELECT t2.b FROM t2 WHERE id < 10);
-- 结果:1,2,3,4,5,6,7,8,9
-- select * from t1 where t1.a in(1,2,3,4,5,6,7,8,9);

-- 实际上在MySQL内部,优化器会改写成如下SQL
-- 实际上在MySQL内部,优化器可能会改写成如下SQL
select * from t1 where exists(select b from t2 where id < 10 and t1.a=t2.b);

-- 不相关子查询变成了关联子查询(select_type:DEPENDENT SUBQUERY),子查询需要根据 b 来关联外表 t1,因为需要外表的 t1 字段,所以子查询是没法先执行的。执行流程如下:
Expand Down
43 changes: 43 additions & 0 deletions docs/optimize/1.overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,49 @@ TPC-H是业界常用的一套Benchmark,由TPC委员会制定发布,用于评
通常比较多使用的百分比响应时间,例如:95%的响应时间都是5毫秒,则表示任务在95%的时间段内都可以在5毫秒之内完成。
将响应时间绘制成折线图或散点图或直方图 ,可以直观地表现出数据结果集的分布情况。

查询响应时间(Query response time )是指MySQL执行查询所需的时间。同义词包括响应时间(response time)、查询时间(query time)、执行时间(execution time),以及(不准确地说)查询延迟(query latency)。

计时开始于MySQL接收查询,结束于它将结果集发送给客户端。


### 查询报告

查询响应时间包括许多阶段(查询执行中的步骤)和等待(锁等待、I/O等待等),但是完整而详细的分解既不可能也不必要。

与许多系统一样,基本的故障排除和分析可以揭示大部分问题。


查询指标提供了有关查询执行的宝贵洞见,包括响应时间、锁定时间、检查的行数等等。但是与所有指标一样,查询指标是原始值,需要被收集、汇总,并以对工程师有意义(且易读)的方式呈现。这正是本节的内容:查询指标工具如何将查询指标转化为查询报告。但是查询报告只是达到目的的手段之一。





#### 聚合

查询指标可以分组和聚合。但是有些查询指标工具可以按用户名、主机名、数据库等进行分组。这些备选分组非常罕见,并且产生了一种不同类型的查询分析。

由于查询响应时间是MySQL性能的“北极星”,将查询指标按查询进行分组是查看哪些查询具有最慢响应时间的最佳方式,这构成了查询报告和分析的基础。


如何唯一标识查询,以确定它们属于哪些分组呢?例如,系统指标(CPU、内存、存储等)按主机名进行分组,因为主机名是唯一且有意义的。

但是,查询没有像主机名那样唯一标识的属性。解决办法是使用SQL语句的标准化形式的摘要。并对摘要文本计算其SHA-256哈希值。

DIGEST TEXT本质是一种SQL语句规范化后将常量替换成'?'的运算结果,STATEMENT_DIGEST_TEXT函数用于计算语句的 DIGEST TEXT(摘要文本)

```sql

SELECT * FROM orders WHERE customer_id=10 AND quantity>20
SELECT * FROM orders WHERE customer_id = 20 AND quantity > 100

SELECT * FROM orders WHERE customer_id = ? AND quantity > ?

f49d50dfab1c364e622d1e1ff54bb12df436be5d44c464a4e25a1ebb80fc2f13

```


**并发性**
并发性是一个非重要

Expand Down

0 comments on commit 8570fdd

Please sign in to comment.