Skip to content

Commit

Permalink
update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
fengzhao committed Dec 25, 2024
1 parent 75ae762 commit f7f6f30
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 3 deletions.
26 changes: 26 additions & 0 deletions docs/basic/9.mysql_architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -1121,6 +1121,32 @@ select count(1) from (select * from A where a>10)A1 Join (select * from B wh

正确性非常容易理解,如果一个改写的结果是错误的,这对业务的价值完全是负面的。完备性同样重要,它要求一个改写算法具有较好的通用性,不能只处理一些简单的场景,而不处理复杂的场景。通用性差对业务的价值是有限的。当然,我们很难把一个改写算法做到完全的完备。因为总有一些非常复杂的情形是很难处理的,强行改写可能会引入正确性问题。在实现一个改写算法的过程中,我们会在确保正确的前提下,尽可能的做到完备。


这个阶段,主要是对原来的语法树进行等价语义的重写,通常是根据预先定义好的规则来进行重写,优化掉一些无效或者无意义的操作。换句话说,有时候程序员写的 SQL 通常是结果导向的,并不专门针对执行去优化,而且,很多时候还会有意无意引入无意义的操作。

```SQL
SELECT
class.name AS class_name,
student.name AS student_name,
student.id AS student_id
FROM
class, student
WHERE
class.id = student.class_id AND
student.name = 'ZhangSan';
```

上述语句返回这个学校所有叫 ZhangSan 的学生的姓名,学号,以及班级。

我们自下而上地来看。首先执行计划要求扫描全表 class 和表 student,然后对其进行 Join,join 条件是 class.id = student.class_id。

join 完之后,对于 tuple 进行 filter,filter 条件是 student.name = 'ZhangSan'。最后,对于 filter 后的 tuple,进行 projection,只有 3 个 column 作为输出 class.name, student.name 和 student.id。


#### 投影下推

`Projections push down`。通过把用到的哪些 column 往下推送直到叶节点的 table scan,可以减少扫描后数据的大小,同时也可以提升扫描速度。

#### 外连接消除

外连接消除的意义:
Expand Down
13 changes: 10 additions & 3 deletions docs/dev/04.MySQL连表查询算法.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
# 连接查询


为什么数据库需要支持 JOIN。这个问题,甚至可以再退一步到为什么数据库需要有多个表?其实答案很简单,上文都提到了:因为现实中的事物就是复杂,多样的。多个表之间的关系能方便地和现实世界的事物映射起来,并且这种映射更直观,更能够让人接受。就像面向对象编程一样,恐怕我们都不能想象如果面向对象编程只能创建一种类型的对象吧。

写过或者学过 SQL 的人应该都知道 left join,知道 left join 的实现的效果,就是保留左表的全部信息,然后把右表往左表上拼接,如果拼不上就是 null。

除了 left join 以外,还有 inner join、outer join、right join,这些不同的 join 能达到的什么样的效果,大家应该都了解了,如果不了解的可以看看网上的帖子或者随便一本 SQL 书都有讲的。
除了方便映射实物,业务逻辑同样需要JOIN。举个例子,假设现在有个简单的电商系统有买家,卖家和订单三张表,数据科学家想要查询 2018 年,对于上海客户的销售额最高的前 3 位卖家信息。这么一个简单的查询其实就用到了每个表里的信息,需要从买家表里得到卖家信息,从买家表里得到地址是上海的买家 ID,然后对订单表以卖家 ID 做组队聚合,最后对销售总额进行排序并取前三


写过或者学过 SQL 的人应该都知道 `left join`,知道 left join 的实现的效果,就是保留左表的全部信息,然后把右表往左表上拼接,如果拼不上就是 null。

除了 left join 以外,还有 `inner join``outer join``right join`,这些不同的 join 能达到的什么样的效果,大家应该都了解了,如果不了解的可以看看网上的帖子或者随便一本 SQL 书都有讲的。

尝试想一想,如果你是MySQL开发者,你会怎么做连表查询的,具体应该用什么算法实现。是一次性把两个表全部load到内存,再去进行关联匹配吗?






join 主要有 Nested Loop、Hash Join、Merge Join 这三种方式,我们这里只讲最普遍的,也是最好的理解的 Nested Loop join 。

Nested Loop join 翻译过来就是 **嵌套循环连接** 的意思,那什么又是嵌套循环呢?嵌套大家应该都能理解,就是一层套一层;那循环呢,你可以理解成是 for 循环。
Expand Down Expand Up @@ -126,7 +134,6 @@ select * from t1 straight_join t2 on (t1.a=t2.a);

**BNL是基于块的嵌套循环连接 Block Nested Loop Join 算法(BNL)**,具体实现大概如下:


把驱动表的数据读入到 **join_buffer** 中,然后扫描被驱动表,**把被驱动表每一行取出来跟 join_buffer 中的数据做对比。**

```sql
Expand Down
8 changes: 8 additions & 0 deletions docs/postgresql/13.深入理解toast技术.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# 什么是 Postgres TOAST?

因为 `postgresql` 的 tuple(行数据)是存在在 `Page` 中的,`Page` 的大小默认为 8KB。postgresql 不允许 tuple 跨页存储,所以当一行数据的某个列数据过大时,比如 `text` 类型的数据,超过了单页的大小,那么 `postgresql` 会将它压缩,切分,并且存储在另外的位置。这种技术就是称为 Toast。

PostgreSQL Toast 使用是通过单个字段的大小来进行判断是否触发此机制的,比如一个字段,超过了`toast_tuple_threshold` 的阈值就会触发字段里面的值,要进行TOAST的工作流程,默认这个字段的值,大小要超过2KB,才会触发。

Postgres 的存储单位称为页,它们具有固定大小(默认为 8 kB)。固定页面大小为 Postgres 带来了许多优势,即数据管理简单、高效和一致性,但它也有一个缺点:某些数据值可能不适合该页面。

0 comments on commit f7f6f30

Please sign in to comment.