了解更多Greenplum技术干货,欢迎访问Greenplum中文社区网站
6月19日,Greenplum原厂内核研发郭峰和大家直播分享了《深入浅出Greenplum内核》系列直播的第三期《Greenplum内核揭秘之查询优化》。没有参加活动的小伙伴也不用失望,我们已经将视频上传至Greenplum中文社区B站频道,通过点击这里即可观看。本文概括了文章的精华内容,欢迎留言交流。
直播视频(腾讯频道)
https://v.qq.com/x/page/i3107m0gi47.html
本文将主要包括两大部分,第一部分是查询优化器的介绍,第二部分是查询优化的具体处理过程,整个过程将被分为四个阶段:查询树的预处理,扫描/连接优化,扫描/连接之外的优化,计划树的后处理,我们将在本文中一一展开。
首先我们来介绍一下查询优化器是做什么的。对于给定的查询语句,查询优化器会找到“代价”最小的查询计划。这里的“代价”在不同的应用场景会有不同的维度或者是定义,比如可能是找到一个执行时间最短,或者找到一个执行占用资源最少的查询计划。
对于同一个查询语句,一般可以由多种方式去执行,因此查询优化器尽可能去遍历每一种可能的执行方式,找到“代价”最小的执行方式,并把它转换成可执行的计划树。
下图是一个例子,A JOIN B on a.i = b.i,对于这个Query,我们有几种执行方式,这里我们来介绍三种执行方式。第一种执行方式中,我们可以先对b做一个索引扫描,再对a做一个顺序扫描,再去执行一个Nested Loop。第二种执行方式中,我们可以对a做一个顺序扫描,把扫描的结果建一个哈希表,再对b做一个顺序扫描,最后用Hash Join得到一个结果。第三种方式是对a做一个顺序扫描,根据a.i为序的键值做一个sort排序,再对b做一个索引扫描,最后做一个Merge Join,得到最后的结果。
大家可以看到这三种执行方式,后面的“代价”(cost)信息是不同的,优化器会根据cost信息选出一个“代价”最小的方式,形成最后的执行方案。
前面介绍了查询优化器,这里我们再来介绍一下查询计划。一个查询计划就是一个由计划节点组成的树,每个计划节点代表了一个特定类型的处理操作,计划节点中包含了执行器执行所需的全部信息。在执行时,计划节点产生输出元组,一般来说,扫描节点从数据表中获取输入元组,大部分其他节点从它们的子计划节点中获取输入元组,并处理产生输出元组。
计划节点可以分为三个类型,
- 扫描节点
包括顺序扫描,索引扫描,位图扫描等;
- 连接节点
包括Nestloop,hash,merge等;
- 非SPJ节点
包括Sort,aggregate,set operations(UNION等)
下面我们再来看一个例子。对于例子中的Query,查询计划就如下图所示,其中Seq Scan on a 和Seq Scan on b都是扫描节点,扫描的结果去做Hash Join,是一个连接节点。Hash Join之上,做了一个HashAggr