深度解析PolarDB数据库并行查询技术

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
RDS PostgreSQL Serverless,0.5-4RCU 50GB 3个月
推荐场景:
对影评进行热评分析
云原生数据库 PolarDB 分布式版,标准版 2核8GB
简介: 随着数据规模的不断扩大,用户SQL的执行时间越来越长,这不仅对数据库的优化能力提出更高的要求,并且对数据库的执行模式也提出了新的挑战。随着数据库在云上的蓬勃发展,越来越多的传统用户迁移到云上,享受云上弹性扩展的红利,但是随着业务的快速扩张,却发现即使动态增加了很多资源,但SQL的执行时间还是越来越慢,并没有随着资源的投入达到预期的效果。显而易见,虽然新增了很多资源,但这些资源并没用被充分利用,很多传统的商业数据库,如Oracle、SQL Server等都提供对并行查询引擎的支持,以充分利用系统资源,达到加速SQL执行的效果。

一  背景


随着数据规模的不断扩大,用户SQL的执行时间越来越长,这不仅对数据库的优化能力提出更高的要求,并且对数据库的执行模式也提出了新的挑战。随着数据库在云上的蓬勃发展,越来越多的传统用户迁移到云上,享受云上弹性扩展的红利,但是随着业务的快速扩张,却发现即使动态增加了很多资源,但SQL的执行时间还是越来越慢,并没有随着资源的投入达到预期的效果。显而易见,虽然新增了很多资源,但这些资源并没用被充分利用,很多传统的商业数据库,如Oracle、SQL Server等都提供对并行查询引擎的支持,以充分利用系统资源,达到加速SQL执行的效果。


本文主要介绍基于代价进行并行优化、并行执行的云数据库的并行查询引擎的关键问题和核心技术。



二  如何将查询并行起来


对于一个类OLAP的查询,显而易见的是它通常是对大批量数据的查询,数据量大意味着数据远大于数据库的内存容量,大部分数据可能无法缓存到数据库的缓冲区中,而必须在查询执行时才动态加载到缓冲区中,这样就会造成大量IO操作,而IO操作又是最耗时的,因此首先要考虑的就是如何能加速IO操作。


由于硬件的限制,每次IO的耗时基本是固定的,虽然还有顺序IO和随机IO的区别,但在SSD已经盛行的今天,两者的差异也在逐渐接近。那么还有没有其它方式可以加速IO呢?显然并行IO是一个简单易行的方法,如果多个线程可以同时发起IO,每个线程只读取部分数据,这样就可以快速将数据读到数据库的缓冲区中。


image.png

并行读取数据的示意如上图所示,每个worker代表一个线程,如果数据已经有partition分区,可以每个线程读取一个partition;也可以将全部数据按固定大小进行分片,比如按一个数据页面大小,然后每个线程以Round-robin模式轮询读取一个分片。


这里需要注意的是,按已有partition分配给不同worker可能会导致每个worker处理的数据不均匀,而按Round-robin模式进行轮询,如果分片设置的比较小,相对来说就比较容易做到每个worker处理的数据比较均匀。


如果只是将数据读取到缓冲区中,而不是立即进行后续处理,那么这些数据就会因缓冲区爆满导致数据被换出,从而失去加速IO的意义。因此,在并行读取数据的同时,必须同时并行处理这些数据,这是并行查询加速的基础。


传统的优化器只能生成串行的执行计划,为了实现并行读取数据,同时并行处理数据,首先必须对现有的优化器进行改造,让优化器可以生成我们需要的并行计划。比如选择哪个表或哪些表可以并行读取,并且通过并行读取会带来足够的收益;或者哪些操作可以并行执行,并且可以带来足够的收益。


并不是说并行化改造一定会有收益,比如对一个数据量很小的表,可能只是几行,如果也对它进行并行读取的话,并行执行所需要的多线程构建再加上线程间的数据同步等所需要的代价可能远大于所得到的收益,总体来说,并行执行会需要更多的资源和时间,这就得不偿失了。因此查询计划的并行化必须是基于代价的,否则可能会导致更严重的性能退化问题。



三  如何选择并行扫描的表


选择并行扫描的表是生成并行计划的重要基础,通过基于并行扫描代价的计算和比较,选择可以并行扫描的表作为候选,是并行执行计划迭代的第一步。基于新的并行代价,也许会有更优的JOIN顺序选择,尤其是当参与JOIN的表的数量比较多时,这需要更多额外的迭代空间,为防止优化过程消耗太多的时间,保持原有计划的JOIN顺序是一个不错的选择。另外,对于参与JOIN的每张表,因为表的访问方法不同,比如全表扫描、Ref索引扫描、Range索引扫描等,这些都会影响到最终并行扫描的代价。


通常我们选择最大的那张表作为并行表,这样并行扫描的收益最大,当然也可以选择多个表同时做并行扫描,后面会继续讨论更复杂的情况。


下面以查询年度消费TOP 10的用户为例:

SELECT c.c_name, sum(o.o_totalprice) as s 
FROM customer c, orders o 
WHERE c.c_custkey = o.o_custkey 
      AND o_orderdate >= '1996-01-01' 
      AND o_orderdate <= '1996-12-31' 
GROUP BY c.c_name 
ORDER BY s DESC 
LIMIT 10;

其中orders表为订单表,数据很多,这类表也被称之为事实表,customer表为客户表,数据相对较少,这类表也被称之为维度表。那么此SQL的并行执行计划如下图所示:

image.png

从计划中可以看出orders表会做并行扫描,由32个workers线程来执行,每个worker只扫描orders表的一部分数据分片,然后与customer表按o_custkey做index lookup进行JOIN,JOIN的结果发送到一个collector组件,然后由collector组件继续做后续的GROUP BY、ORDER BY及LIMIT操作。



四  选择多表并行的JOIN


将一张表做并行扫描之后,就会想为什么只能选择一张表?如果SQL中有2张或更多的FACT表,能不能可以将FACT表都做并行扫描呢?答案是当然可以。以下面SQL为例:

SELECT o.o_custkey, sum(l.l_extendedprice) as s 
FROM orders o, lineitem l 
WHERE o.o_custkey = l.l_orderkey 
GROUP BY o.o_custkey 
ORDER BY s 
LIMIT 10;

其中orders表和lineitem表都是数据量很大的事实表,此SQL的并行执行计划如下图所示:image.png

从计划中可以看到orders表和lineitem表都会做并行扫描,都由32个workers线程来执行。那么多个表的并行是如何实现的呢?我们以2个表为例,当2个表执行JOIN时,通常的JOIN方式有Nested Loop JOIN、HASH JOIN等,对于不同的JOIN方式,为保证结果的正确性,必须选择合理的表扫描方式。


以HASH JOIN为例,对于串行执行的HASH JOIN来说,首先选择一个表创建HASH表称之为Build表,然后读取另一个Probe表,计算HASH,并在Build表中进行HASH匹配,若匹配成功,输出结果,否则继续读取。如果改为并行HASH JOIN,并行优化器会对串行执行的HASH JOIN进行并行化改造,使之成为并行HASH JOIN,并行化改造的方案可以有以下两种解决方案。


方案一是将2个表都按HASH key进行分区,相同HASH值的数据处于同一个分区内,由同一个线程执行HASH JOIN。方案二是创建一个共享的Build表,由所有执行HASH JOIN的线程共享,然后每个线程并行读取属于自己线程的另外一个表的分片,再执行HASH JOIN。最终选择哪种方案,通过代价估算来决定。

image.png

并行HASH JOIN示意图


  • 对于方案一,需要读取表中的所有数据,根据选中的HASH key,对数据进行分区,并将数据发送到不同的处理线程中,这需要额外增加一个Repartition算子,负责根据分区规则将数据发送到不同的处理线程。


  • 对于方案二,需要并行创建共享的HASH build表,当build表创建成功后,每个线程读取Probe表的一个分片,分别执行HASH JOIN,这里的分片并不需要按照HASH key进行分片,每个线程分别读取互不相交的分片即可。


五  分析统计的复杂算子的并行


对于一个分析统计的需求,GROUP BY操作是绕不开的操作,尤其对大量的JOIN结果再做GROUP BY操作,是整个SQL中最费时的一个过程,因此GROUP BY的并行也是并行查询引擎必须优先解决的问题。


以年度消费TOP10客户的SQL为例,对GROUP BY并行化后的并行执行计划如下图所示:


image.png

与之前的执行计划相比,新的执行计划中多了一个collector组件,总共有2个collector组件。首先我们看第二行的collector组件,它的extra信息中有2条"Using temporary; Using filesort",这表示它是对从workers接收到的数据执行GROUP BY,然后再按ORDER排序,因为只有第一个collector组件在用户的session中,所以这个collector也是在worker中并行执行,也就是说并行的做Group by和Order by以及Limit;然后看第一行的collector组件,它的extra信息中只有一条"Merge sort",表示session线程对从workers接收到的数据执行一次merge sort,然后将结果返回给用户。这里可能就有人会提出疑问,为什么session线程只做merge sort就可以完成GROUP BY操作呢?另外LIMIT在哪里呢?


首先回答第2个问题,因为explain计划显示的问题,在常规模式下不显示LIMIT操作,但在Tree模式下会显示LIMIT操作。如下所示:

image.png

从Tree型计划树上可以清楚的看到LIMIT操作有2处,一处在计划的顶端,也就是在session上,做完limit后将数据返回给用户;另外一处在计划树的中间位置,它其实是在worker线程的执行计划上,在每个worker线程中在排序完成后也会做一次limit,这样就可以极大减少worker返回给session线程的数据量,从而提升整体性能。


下面来回答第一个问题,为什么GROUP BY只需要在worker线程上执行一次就可以保证结果的正确性。通常来说,每个worker只有所有数据的一个分片,只在一个数据分片上做GROUP BY是有极大的风险得到错误的GROUP BY结果的,因为同一GROUP分组的数据可能不只是在本WORKER的数据分片上,也可能在其它WORKER的数据分片中,被其它WORKER所持有。但是如果我们可以保证同一GROUP分组的数据一定位于同一个数据分片,并且这个数据分片只被一个WORKER线程所持有,那么就可以保证GROUP BY结果的正确性。通过Tree型执行计划可以看到,在并行JOIN之后,将JOIN的结果按GROUP分组的KEY值: c.c_name进行Repartition操作,将相同分组的数据分发到相同的WORKER,从而保证每个WORKER拥有的数据分片互不交叉,保证GROUP BY结果的正确性。


因为每个WORKER的GROUP BY操作已经是最终结果,所以还可以将ORDER BY和LIMIT也下推到WORKER来执行,进一步提升了并行执行的效率。



六  并行查询引擎对TPCH的线性加速


附图是一个并行查询引擎对TPCH的加速效果,TPC-H中100%的SQL可以被加速,70%的SQL加速比超过8倍,总和加速近13倍,Q6和Q12加速甚至超过32倍。

image.png

七  总结


数据库是应用系统的核心,而优化器是数据库的核心,优化器的好坏几乎可以决定一个数据库产品的成败。开发一个全新的优化器,对任何团队都是一个巨大的挑战,技术的复杂度暂且不提,就是想做到产品的足够稳定就是一个非常难以克服的困难。因此即使传统商业数据库,也是在现有优化器的基础上不断改进,逐渐增加对并行的支持,最终成为一个成熟的并行优化器。对PolarDB也是如此,在设计和开发并行查询引擎时,我们充分利用现有优化器的技术积累和实现基础,不断改进,不断打磨,最终形成了一个持续迭代的技术方案,以保证新的优化器的稳定运行和技术革新。



相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
9天前
|
存储 NoSQL 关系型数据库
非关系型数据库-MongoDB技术(二)
非关系型数据库-MongoDB技术(二)
|
9天前
|
NoSQL 关系型数据库 MongoDB
非关系型数据库-MongoDB技术(一)
非关系型数据库-MongoDB技术(一)
|
7天前
|
存储 Cloud Native 关系型数据库
Ganos实时热力聚合查询能力解析与最佳实践
Ganos是由阿里云数据库产品事业部与飞天实验室共同研发的新一代云原生位置智能引擎,集成于PolarDB-PG、Lindorm、AnalyticDB-PG和RDS-PG等核心产品中。Ganos拥有十大核心引擎,涵盖几何、栅格、轨迹等多种数据处理能力,实现了多模多态数据的一体化存储、查询与分析。本文重点介绍了Ganos的热力瓦片(HMT)技术,通过实时热力聚合查询与动态输出热力瓦片,无需预处理即可实现大规模数据秒级聚合与渲染,适用于交通、城市管理、共享出行等多个领域。HMT相比传统网格聚合技术具有高效、易用的优势,并已在多个真实场景中验证其卓越性能。
21 0
|
4天前
|
域名解析 网络协议 安全
DNS查询工具简介
DNS查询工具简介
16 4
|
21天前
|
关系型数据库 MySQL 分布式数据库
PolarDB MySQL数据库场景体验与测评
本文介绍如何在PolarDB上部署数据库,包括登录控制台、配置账号与数据库管理、执行SQL查询及调整Serverless配置等内容。通过创建测试表和数据操作演示了基本数据库管理功能,并展示了如何设置资源弹性扩缩、监控及备份数据。此外,还提供了关于节点切换、压测、加速复杂SQL查询、弹性并行查询及高可用性的详细场景体验说明,全方位展示了PolarDB的强大功能。
|
12天前
|
关系型数据库 分布式数据库 数据库
来!跟通义灵码一起参加PolarDB 数据库创新设计赛,突破传统,探索人机协作
无论你是数据库新手,还是技术大咖,通义灵码邀请你参加2024 年全国大学生计算机系统能力大赛 PolarDB 数据库创新设计赛(天池杯),新参赛模式启动,挑战极限!
|
16天前
|
存储 关系型数据库 分布式数据库
揭秘PolarDB:中国云原生数据库的超级英雄,如何颠覆传统数据存储?
在数字化时代,数据成为企业的核心资产,而云原生数据库则是推动企业转型的关键。PolarDB凭借其先进的存储计算分离架构,在性能、可靠性和易用性方面脱颖而出,成为国内领先的选择。它支持多种数据库引擎,提供多副本存储机制,并采用按量付费模式,有效降低管理和成本压力,助力企业实现高效、可靠的数字化转型。
30 1
|
21天前
|
存储 负载均衡 数据库
探索后端技术:从服务器架构到数据库优化的实践之旅
在当今数字化时代,后端技术作为支撑网站和应用运行的核心,扮演着至关重要的角色。本文将带领读者深入后端技术的两大关键领域——服务器架构和数据库优化,通过实践案例揭示其背后的原理与技巧。无论是对于初学者还是经验丰富的开发者,这篇文章都将提供宝贵的见解和实用的知识,帮助读者在后端开发的道路上更进一步。
|
22天前
|
关系型数据库 MySQL Serverless
探索PolarDB MySQL版:Serverless数据库的灵活性与性能
本文介绍了个人开发者对阿里云PolarDB MySQL版,特别是其Serverless特性的详细评测体验。评测涵盖了产品初体验、性能观测、Serverless特性深度评测及成本效益分析等方面。尽管试用过程中遇到一些小问题,但总体而言,PolarDB MySQL版表现出色,提供了高性能、高可用性和灵活的资源管理,是个人开发者和企业用户的优秀选择。
|
2月前
|
关系型数据库 MySQL 分布式数据库
PolarDB 与传统数据库的性能对比分析
【8月更文第27天】随着云计算技术的发展,越来越多的企业开始将数据管理和存储迁移到云端。阿里云的 PolarDB 作为一款兼容 MySQL 和 PostgreSQL 的关系型数据库服务,提供了高性能、高可用和弹性伸缩的能力。本文将从不同角度对比 PolarDB 与本地部署的传统数据库(如 MySQL、PostgreSQL)在性能上的差异。
85 1

相关产品

  • 云原生数据库 PolarDB
  • 推荐镜像

    更多
    下一篇
    无影云桌面