MPP数据库实现入门

MPP数据库实现入门大规模并行分析 MPP 数据库自诞生以来 为数据驱动型企业提供了巨大的机会 近日 HashData 联合创始人王占伟围绕 MPP 数据库的基础原理及技术特点与网友进行了分享交流 本文摘选部分精彩观点 与大家共享 如上图所示 MPP 数据库内核主要包括模块查询 编译查询 优化任务调度查询 执行存储 MPP 数据库的 API applicationp 或者命令行接收到了 SQL 查询请求之后 系统先经过查询编译 然后查询优化 通过任务调度执行从存储引擎里面把数据拉出来 计算出结果

在这里插入图片描述
大规模并行分析(MPP)数据库自诞生以来,为数据驱动型企业提供了巨大的机会。近日,HashData联合创始人王占伟围绕MPP数据库的基础原理及技术特点与网友进行了分享交流。本文摘选部分精彩观点,与大家共享。
图片
如上图所示,MPP数据库内核主要包括模块查询、编译查询、优化任务调度查询、执行存储。


MPP数据库的API(application programming interface )或者命令行接收到了SQL查询请求之后,系统先经过查询编译,然后查询优化,通过任务调度执行从存储引擎里面把数据拉出来,计算出结果,再返回一个结果集给客户。图片
在数据库里面遇到的第一个模块叫查询编译。查询编译分大概分为三大块:词法分析、语法分析、语义检查。

一个查询语句,经过词法分析、语法分析、语义检查生成的结果叫做query tree,在经过优化器之后叫做 plan tree ,这个就是编译的作用。

查询编译模块在整个数据库里面是最基础的。查询编译之后的过程是查询优化。查询优化器主要负责两个功能:逻辑优化和物理优化。

逻辑优化是指基于关系代数的理论,把查询语句的 SQL 语句做一些等价变换。这里要注意的是,“等价”非常重要,如果把一个 SQL 语句变成了不等价的,结果就会出错。等价变换的目的是为了提供更多可用来参考这个查询计划的解空间。

物理优化是指选择最优的物理方案。选择优化的依据有两种,一种是基于规则的优化,在做等价变换的时候,如果变换之后的这个执行方案一定比变换之前的更优秀,那么会选择等价变换;如果变换之后的方案不一定更优秀,那就要考虑变换之前和变换之后的两种方案。前者相当于去做了剪枝,把解空间减掉了一半,后者相当于把解空间增加了一半。

第二类依据是基于代价的查询优化,接下来会重点讲述依据代价的查询优化。图片
以上图为例,要做到三表关联,关联操作要满足交换率和结合率。通过计算可以得出三种可能的执行方式。这三种方式里面哪种更优秀呢?这个时候要去进行评估,付出的成本越小,这个方案就越好。这样产生的查询计划就是基于代价的查询优化。图片接下来讲查询优化的代价模型。什么是代价模型?代价是怎么算出来的?代价就是服务器用了多少 CPU访问多少磁盘。在算法确定的情况下,网络连接其实是确定的,就能算出来一个操作所需要的开销。每一个操作的开销算出来之后,整个查询计划的开销也就能算出来。

查询计划准确度统计取决于信息的准确度GIGO、模型的准确度、代价模型的前置依赖等几个因素。

统计信息是基于代价的查询优化器的输入,如果统计信息不准,那它输出的查询计划一定是垃圾。

影响准确度的第二个因素就是模型是不是准确,因为一个算法,一个数据库的算法的模型是非常复杂的。模型能不能高度还原你的算法,对于查询计划准确度很重要。

代价模型普遍都有一些前置条件,假设这些模型没有相关性,那算出来一定是错的。

第一种方式叫做拉模式,这也是目前普遍采用的一种方式。拉模式可以理解为所有的计算机一起工作,一台机器计算出来一个数据后,交给下一台机器接着算,就像流水线上的工人一样。

在分布式数据库里,有两类数据的链路交换。一类数据是控制流,它传递的是这个控制命令,传递的是 plan 和一些控制的结果。执行的结果成功了还是失败了、有没有报错、错误信息是什么等都是这类结果。

另外一类的数据通路是数据流,也就是tuple 数据,motion节点处理的都是tuple 数据。这个数据流量非常大,它不像控制流比较小。它有一个特点,就是基于 TCP 协议去实现这个 motion 节点数据交换。图片
分布式数据库执行器如何去实现聚集操作?我们通常有三种处理方式:一阶段聚集、两阶段聚集、三阶段聚集。

一阶段聚集,是指这个聚集操作只有一台机器执行,和单机数据库一样。它的优点是简单,缺点就是慢,适用于数据量较少的场景。

两阶段聚集是分布式系统中最常见一个方法。这种方法先在每个节点上计算一遍 sum 中间结果,这样能减少数据总量,降低传输的代价,而且不同节点的 sum 都是并行计算的。

实向量化和代码生成并不能提升 IO 的性能。以上图为例,就是计算一个元组所需要的指令周期。

解释执行的成本在于抽象的代价。那么怎么能把这些解释执行的代价降到最低?主要有两种手段,一种手段是使用计时编译的方法,这样生成的代码是非常紧凑的,消除了不必要的分支,消除了抽象的代价,并且进行了内链优化。这意味着可以把解释执行的成本降得非常低。

第二个方式就是提升分母,以此来摊薄解释执行的成本,这就是向量化。

向量化也好,还是用Jit计时编译的方法也好,都可以使用一个叫做SIMD指令。

SIMD指令是 CPU 提供的一种功能,它可以让用户以一条指令来计算多个数据。所以不论是内链优化、Jit 还是向量化,都可以用上SIMD指令。

具体实现过程中,向量化的实现可能相对来说容易一些,而运行器代码生成在做代码调试的时候相当的痛苦。我们通常选择其中一种来做。但实际上两种结合一起做 Jit 的方式在处理表达式计算的时候是非常有效的。同样的,我们也可以把它运用到元组解析上。图片
最后我们要讲的主题是存储引擎。通常大家谈论存储的时候,经常提到列存。那什么是列存?列存和行存有什么区别?

如上图所示,把数据以行的形式存放,一行存完了再存下一行,下一行存完了再存下一行,这是按行来存,叫做行存。行存主要面向事务型应用。

列存是指同一条数据被拆散在了不同的地方存储,同一列的数据、同一类型的数据紧密地存放在一起。列存主要面向分析型事务,具有更高效的压缩、节省IO等优势,缺点是对内存消耗较大。图片
那么分布式数据库的存储有什么特点呢?分布式数据库在存储方面一个十分重要的的概念叫做数据分布。刚才讲的分布式数据库会有很多个节点,每个节点处理的是不同的数据。那这个数据怎么来区别?谁处理哪些数据呢?这就考虑到数据分布了。

数据分布通常我们有两种办法:一种是随机分布;另一种是哈希分布,计算一个哈希值,然后分给大家,这样分布式比较有规律。图片存储引擎在设计时要考虑高可用。什么叫高可用?通常的做法是增加副本的数量。那么,增加副本的数量又会带来新的问题,即怎么保证副本之间的数据是一样的呢?现阶段常见的办法是采用一致性协议,比如状态机复制,从而保证多个副本之间的一致性,不会造成丢失数据。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/216974.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 上午10:38
下一篇 2026年3月18日 上午10:38


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号