简介:PolarDB与开源MySQL及其它类MySQL的产品相比,除了计算与存储拆散的先进架构之外,另外一个最外围的技术冲破就是开发了其它类MySQL产品没有的并行查问引擎,通过并行查问引擎,PolarDB除了放弃本身对OLTP利用的劣势之外,还对OLAP的反对能力有了一个质的飞越,遥遥领先于其它类MySQL产品。
PolarDB与开源MySQL及其它类MySQL的产品相比,除了计算与存储拆散的先进架构之外,另外一个最外围的技术冲破就是开发了其它类MySQL产品没有的并行查问引擎,通过并行查问引擎,PolarDB除了放弃本身对OLTP利用的劣势之外,还对OLAP的反对能力有了一个质的飞越,遥遥领先于其它类MySQL产品。
用户越来越多的剖析统计需要
家喻户晓,MySQL的优化器目前还不反对并行优化,也不反对并行执行。当然,MySQL本人也在逐步摸索并行执行的可能,比方对count(*)的并行执行,但整体上,还没有造成一套成熟的并行优化、并行执行的机制,只是针对一些非凡的场景进行局部优化。随着类MySQL产品在云上的蓬勃发展,越来越多的传统用户迁徙到类MySQL产品上,对MySQL提出了一些新的挑战。很多传统用户在对OLTP要求的同时,还要求数据库有一些剖析、统计、报表的能力,绝对传统商业数据库来说,MySQL在这方面有显著的劣势。为了满足用户一直晋升的OLTP能力,同时又能进行OLAP剖析的需要,PolarDB的并行查问引擎应运而生。自诞生以来,通过弱小的并行执行能力,原来须要几百秒的查问,当初只须要几秒,为用户节俭了大量的工夫和金钱,失去大量用户的极大好评。
PolarDB并行查问引擎应运而生
优化器是数据库的外围,优化器的好坏简直能够决定一个数据库产品的成败。开发一个全新的优化器,对任何团队都是一个微小的挑战,技术的复杂度暂且不提,就是想做到产品的足够稳固就是一个十分难以克服的艰难。因而即便传统商业数据库,也是在现有优化器的根底上不断改进,逐步减少对并行的反对,最终成为一个成熟的并行优化器。对PolarDB也是如此,在设计和开发并行查问引擎时,咱们充分利用现有优化器的技术积攒和实现根底,不断改进,一直打磨,最终造成了一个继续迭代的技术计划,以保障新的优化器的稳固运行和技术革新。
对于一个类OLAP的查问,不言而喻的是它通常是对大批量数据的查问,数据量大意味着数据远大于数据库的内存容量,大部分数据可能无奈缓存到数据库的buffer中,而必须在查问执行时才动静加载到buffer中,这样就会造成大量IO操作,而IO操作又是最耗时的,因而首先要思考的就是如何能减速IO操作。因为硬件的限度,每次IO的耗时根本是固定的,尽管还有程序IO和随机IO的区别,但在SSD曾经流行的明天,两者的差别也在逐步靠近。那么还有没有其它形式能够减速IO呢? 显然并行IO是一个简单易行的办法,如果多个线程能够同时发动IO,每个线程只读取局部数据,这样就能够疾速的将数据读到数据库的buffer中。然而如果只是将数据读取到buffer中,而不是立刻进行后续解决,那么这些数据就会因buffer爆满导致数据被换出,从而失去减速IO的意义。
图1-并行IO示意图
因而,在并行读取数据的同时,必须同时并行的解决这些数据,这是并行查问减速的根底。因为原有的优化器只能生成串行的执行打算,为了实现并行读取数据,同时并行处理数据,首先必须对现有的优化器进行革新,让优化器能够生成咱们须要的并行打算。比方哪些表能够并行读取,并且通过并行读取会带来足够的收益;或者哪些操作能够并行执行,并且能够带来足够的收益。并不是说并行化革新肯定会有收益,比方对一个数据量很小的表,可能只是几行,如果也对它进行并行读取的话,并行执行所须要的多线程构建所须要的代价可能远大于所失去的收益,总体来说,并行读取会须要更多的资源和工夫,这就得失相当了,因而并行化的革新必须是基于代价的,否则可能会导致更重大的性能褪化问题。
Fact表的并行扫描
通过基于并行cost的计算和比拟,抉择能够并行读取的表作为候选,是并行执行打算的第一步。基于新的并行cost,兴许会有更优的JOIN的程序抉择,但这须要更多的迭代空间,为避免优化过程耗费太多的工夫,放弃原有打算的JOIN程序是一个不错的抉择。另外,对于参加JOIN的每张表,因为表的拜访办法不同,比方全表扫描、ref索引扫描,range索引扫描等,这些都会影响到最终并行扫描的cost。
通常咱们抉择最大的那张表作为并行表,这样并行扫描的收益最大,当然也能够抉择多个表同时做并行扫描,前面会持续探讨更简单的状况。
上面以查问年度生产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表为订单表,数据很多,这类表称之为Fact事实表,customer表为客户表,数据绝对较少,这类表称之为dimension维度表。那么此SQL的并行执行打算如下图所示:
从打算中能够看出orders表会做并行扫描,由32个workers线程来执行,每个worker只扫描orders表的某些分片,而后与customer表按o\_custkey做eq\_ref进行JOIN,JOIN的后果发送到用户session中一个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表都是数据量很大的FACT表,此SQL的并行执行打算如下图所示:
从打算中能够看到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。
图2-并行HASH JOIN示意图
- 对于计划一,须要读取表中的所有数据,依据选中的HASH key,对数据进行分区,并将数据发送到不同的解决线程中,这须要额定减少一个Repartition算子,负责依据分区规定将数据发送到不同的解决线程。为了提高效率,这里通常会采纳message queue队列来实现。
- 对于计划二,须要并行创立共享的HASH build表,当build表创立胜利后,每个线程读取Probe表的一个分片,别离执行HASH JOIN,这里的分片并不需要依照HASH key进行分片,每个线程别离读取互不相交的分片即可。
剖析统计算子的并行
对于一个剖析统计的需要,GROUP BY操作是绕不开的操作,尤其对大量的JOIN后果再做GROUP BY操作,是整个SQL中最费时的一个过程,因而GROUP BY的并行也是并行查问引擎必须优先解决的问题。
以年度生产TOP10客户的SQL为例,对GROUP BY并行化后的并行执行打算如下图所示:
与之前的执行打算相比,新的执行打算中多了一个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操作。如下所示:
从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倍。
一直迭代翻新的并行查问引擎
总之,通过对并行查问引擎的反对,PolarDB不仅在放弃查问引擎稳固的同时,还极大的晋升了简单SQL,尤其是剖析统计类型查问的性能。通过有打算的一直迭代,PolarDB在并行查问引擎的路线上越走越远,也越来越弱小,为了满足客户日益一直增长的性能需求,为了更多企业用户的数字化降级,PolarDB为您提供革命性的数据引擎,助您减速拥抱万物互联的将来。
版权申明:本文内容由阿里云实名注册用户自发奉献,版权归原作者所有,阿里云开发者社区不领有其著作权,亦不承当相应法律责任。具体规定请查看《阿里云开发者社区用户服务协定》和《阿里云开发者社区知识产权爱护指引》。如果您发现本社区中有涉嫌剽窃的内容,填写侵权投诉表单进行举报,一经查实,本社区将立即删除涉嫌侵权内容。