时间戳(timestamp)是分布式事务中绕不开的重要概念,有意思的是,现在主流的几个分布式数据库对它的实现都不尽相同,甚至是主要区分点之一。本文聊一聊时间戳的前世今生,为了把讨论集中在主题上,假设读者已经对数据库的 MVCC、2PC、一致性、隔离级别等概念有个基本的了解。
YugabyteDB 介绍
Yugabyte DB 是一个全球部署的分布式数据库,和国内的 TiDB 和国外的 CockroachDB 类似,也是受到 Spanner 论文启发,所以在很多地方这几个数据库存在不少相似之处。
与 Cockroach 类似,Yugabyte 也主打全球分布式的事务数据库——不仅能把节点部署到全球各地,还能完整支持 ACID 事务,这是他最大的卖点。除此以外还有一些独特的特性,比如支持文档数据库接口。如果我猜的没错,Yugabyte 早期被设计成一个文档数据库,后来才调整技术路线开始主打 SQL 接口。
G1 垃圾收集器
在过去很长一段时间内,HotSpot JVM 的首选垃圾收集器都是 ParNew + CMS 组合。直到 JDK7 中 Hotspot 团队首次公布了 G1(Garbage-First),并在 JDK9 中用 G1 作为默认的垃圾收集器。我们团队最近也将用了很多年的 CMS 换成了 G1 垃圾收集器。
本文主要从 G1 的论文 Garbage-First Garbage Collection 出发,结合其他较新的白皮书等,讲解 G1 垃圾收集器的工作原理。
SQL 窗口函数的优化和执行
窗口函数(Window Function)是 SQL2003 标准中定义的一项新特性,并在 SQL2011、SQL2016 中又加以完善,添加了若干处拓展。窗口函数不同于我们熟悉的普通函数和聚合函数,它为每行数据进行一次计算:输入多行(一个窗口)、返回一个值。在报表等分析型查询中,窗口函数能优雅地表达某些需求,发挥不可替代的作用。
本文首先介绍窗口函数的定义及基本语法,之后将介绍在 DBMS 和大数据系统中是如何实现高效计算窗口函数的,包括窗口函数的优化、执行以及并行执行。
SQL 子查询的优化
子查询(Subquery)的优化一直以来都是 SQL 查询优化中的难点之一。关联子查询的基本执行方式类似于 Nested-Loop,但是这种执行方式的效率常常低到难以忍受。当数据量稍大时,必须在优化器中对其进行去关联化(Decoorelation 或 Unnesting),将其改写为类似于 Semi-Join 这样的更高效的算子。
前人已经总结出一套完整的方法论,理论上能对任意一个查询进行去关联化。本文结合 SQL Server 以及 HyPer 的几篇经典论文,由浅入深地讲解一下这套去关联化的理论体系。它们二者所用的方法大同小异,基本思想是想通的。
JIT 代码生成技术(二)查询编译执行
代码生成(Code Generation)技术广泛应用于现代的数据系统中。代码生成是将用户输入的表达式、查询、存储过程等现场编译成二进制代码再执行,相比解释执行的方式,运行效率要高得多。
上一篇文章 代码生成技术(一)表达式编译 中提到,虽然表面上都叫“代码生成”,但是实际可以分出几种粒度的实现方式,比如表达式的代码生成、查询的代码生成、存储过程的代码生成等。今天我们要讲的是查询级别的代码生成,有时也称作算子间(intra-operator)级别,这也是主流数据系统所用的编译执行方式。
从 Weld 论文看执行器的优化技术
Weld 是一个用于数据计算分析的高性能 Runtime(High-performance runtime for data analytics applications),使用 Rust 编写,可以很容易地集成到各种大数据计算框架中,比如 Spark SQL、NumPy & Pandas、TensorFlow 等,带来大幅的性能提升。
除了 Weld 本身的贡献,论文中提到的各种用于执行阶段的优化技术也很有意思,其中的大部分都借鉴自关系型数据库或编译器。本文除了介绍 Weld 之外,也是想对这些技术做个梳理。
本文主要内容来自于 Weld 发表在 VLDB'18 的论文。
CompletableFuture 也没有那么废柴嘛!
上篇文章中提到,Java 里把 Promise 叫作 CompletableFuture,相比那个只能用于线程同步的 Future,它新增了很多方法用于串联异步事件,比如常用的 thenApply
、thenCompose
、thenAccept
等。
如果不引入任何第三方库,CompletableFuture 仍是目前 Java 上最好的异步编程方式。之前一直觉得这个东西难用,直到我想明白一件事,证明了 CompletableFuture 虽然麻烦了点但是能做任何事情,然后用它的时候心里就没那么膈应了。
本文会以一个例子来讲解:如何把任意函数转换成异步调用风格。其实不一定要用 CompletableFuture,任何语言和框架都是适用的。
JIT 代码生成技术(一)表达式编译
代码生成(Code Generation)技术广泛应用于现代的数据系统中。代码生成是将用户输入的表达式、查询、存储过程等现场编译成二进制代码再执行,相比解释执行的方式,运行效率要高得多。尤其是对于计算密集型查询、或频繁重复使用的计算过程,运用代码生成技术能达到数十倍的性能提升。