学习让我快乐

争于世, 不争于势;简洁, 高效, 赏心悦目

GP 存储计算分离的一种实现

效果 和 presto 中将执行计划切分为多个 Stage 一样, GP 也会将执行计划切分为多个 Slice, 每一个 slice 表示着执行的一个阶段. 在优化阶段, 在 PG 优化器的基础之上, GP 会根据表数据的分布策略在合适的地方加入 Motion 节点, Motion 节点用来根据需要对数据进行重分布. 在优化结束, 执行计划确定了之后, GP 会遍历 plan tree, ...

GP udpifc interconnect 两三事

GP interconnect 层, 对上提供了一种可靠有序的数据传输方式, 在查询执行中计算节点之间通过 GP interconnect 层来完成所需的数据交互. 当前 GP 中 interconnect 主要有两种实现: tcp, udpifc. 其中 tcp 便是直接基于 TCP 搭建; udpifc 则是基于 UDP 协议实现, 在 UDP 基础之上加入了 ACK, 重传等机制来实现...

QUIC 与 mvfst

前言 这篇文章记录了我在学习 QUIC 协议以及阅读 facebook/mvfst 代码时随手记得一些笔记, 并没有多大的条理性以及可读性. 对于第三者读者而言, 老实说并没有多大的价值… 之所以对 QUIC 感兴趣, 是因为想用此替换下 Greenplum 这一 MPP 数据库的 interconnect 层. 当前 Greenplum interconnect 层主要有两种实现: T...

PG 中的 builtin function

PG 的 CREATE FUNCTION 支持用户在 create function 时使用 language internal. 此时 AS 子句中跟着的是 PG builtin function 的函数名. 如下所示: CREATE FUNCTION myfloat4abs(float4) RETURNS float4 LANGUAGE internal AS 'float4abs' ...

一个普通的遍历实现

最近在看 Greenplum 代码时发现一个比较有意思的代码片段, 这个代码片段解决了一个比较有意思的问题. 抽象着来说, 便是对于一个长度为 N 的数组 A, 数组 A 中每一个元素自身也是一个数组, 记集合 \(\{ M_1, M_2,..., M_N \}\) 为一个组合, 其中 \(M_i\) 为 A[i] 指向数组中成员之一. 现在需要设计一个过程可以完成对所有组合的遍历工作. ...

PG 中的优化器: 概念

本文章内容根据 PG9.6 代码而来. 我个人感觉, 对 PG 优化器的学习一定要切合一个特定的链路, 更细化地说是一个特定的查询. 因为 PG 优化器被用来处理所有可能的查询, 它里面包含了大量的分支判断, 虽然 PG 将若干分支进行了一定的抽象汇总, 但是如果没有特定查询场景下, 咋一看也是有点蒙的. 另外该篇文章主要着重于对优化过程中所用到的各种概念的描述, 并未太过详细地描...

21亿次事务之后...

最近在看 Greenplum 的分布式事务执行框架, 发现了一个较为有意思的 bug, 该 bug 出现在判定分布式事务先后次序的逻辑上面, 会导致在执行 21 亿事务之后, 准确来说是 2147483659 次事务之后, 后续的分布式事务可能会构造出错误的分布式快照, 导致了之前的事务插入的数据对之后的事务不再可见. 为了能够搞清楚这个 bug 是怎么发生的, 我们先简单介绍下 GP 中的...

PG 中的事务: XLOG

本文章内容根据 PG9.6 代码而来. XLOG, 也即 WAL 在 PG 中的别称, 我们这里不对 WAL 背后的细节背景做过多介绍, 更专注与 PG 中是如何实现 WAL 的, 即 PG 的 XLOG 模块. 在 PG 之中, 每一条 XLOG 都对应着一个 XLogRecord, 其内存放着所有与当前 XLOG 相关的信息, 大致来说主要就是: 当前 XLO...

指令级优化参考手册: 三

最近在做的一些事对性能要求极其苛刻, 以至于最后不得不下潜到指令级找寻一些可能存在的优化点. 这里总结记录了在此过程中所得到的一些通用化优化规则. 在试图应用这些规则来优化自己的程序之前要首先铭记先贤们说过的: “过早优化是万恶之源”. 因此我们建议除非是使用了 perf 等工具找到了程序热点, 否则不应该首先应用这些规则来对程序进行优化. 我个人认为在写代码的过程中惦记着怎么把这段代码最优...

为什么 unlock 时没有唤醒我?

还是我们的 ADB PG 测试实例, 收到了测试脚本执行超时的报警, 看了一下发现是由于已经执行很久的 DELETE 持有的锁阻塞了测试脚本中 DDL 的执行, 又看了一下这个 DELETE backend 的堆栈: #0 0x00002b2049a2af67 in semop () from /lib64/libc.so.6 #1 0x0000000000770bc4 in PGSe...

SIGUSR2 导致的血案

有一天忽然收到我们 ADB PG 测试实例重启的报警, 当时上去看了下发现是实例部署个关于内存控制的参数没配置合适导致计算节点 OOM 了, 恰好当时 master 在处于恢复残留两阶段事务的关键链路, 发现无法链接 segment, 毕竟此时 segment 处于 recovery mode, 便 PANIC 退出了. 当时按照预案配置好相关参数, 理论上是需要一次重启才能使实例生效的, ...

函数调用的背后

一般情况下, 我们很少会关注函数调用是如何实现的, 反正大概就是压栈出栈什么的. 但是在我们 debug 时, 尤其是在 debug coredump 时, 知道这背后的细节还是会起到很大帮助的. 如我们在 debug qtcreator 时, 见 为什么我的 QtCreator 看不了 GCC 源码. 之前我对这方面的掌握一直零零散散的, 这里总结一下. 目前据我所知, 编译器在实现函数...

PG 的扩展性: 类型

如果需要在系统中实现一个支持用户自定义数据类型的功能, 你该怎么做? 如果是我的话, 我在系统中将只负责为这个数据类型提供一个定长/变长的存储空间, 之后关于对这个存储空间的使用与解析全部交于用户去做. 在 PG 中, 也是类似做法. PG 中使用长度固定为 8 字节(起码在 64 位机器上)的 Datum 来表示所有的用户数据类型. 即 Datum 肩负着在 PG 内核与用户代码之间传递数...