在数据库技术领域,面对大规模数据集与高并发访问场景,单一处理器系统已无法满足现代应用对性能与吞吐量的要求。为提升处理能力和系统可扩展性,并行数据库系统应运而生,其核心理念在于将大规模查询与数据操作任务分解后,分布于多个计算资源并发执行,以突破单节点系统的性能瓶颈。

事实上,约二十年前并行数据库的发展前景曾一度受到质疑,甚至部分业内专家也表示谨慎观望。然而,随着数据体量的指数级增长和业务需求的提升,并行数据库已跃升为主流,各大数据库厂商均在积极推动并行架构相关产品化落地。
尤其在互联网应用爆发式增长背景下,数据库面临的存储压力与实时响应需求显著增加,如电商平台需支撑数以百万计用户的行为数据实时处理,传统单处理器架构已难以保障系统的高可用与高性能。现代多核处理器的普及及其成本的下降,极大地促进了并行处理硬件基础的普及。 而从数据库本身来看,SQL及关系型操作的面向集合特性极易被解耦为若干并发任务,因此,数据库天然适合在并行计算环境下实现高效处理。
并行数据库系统可以采用不同的架构模式,每种都有其独特的优势和适用场景:
I/O并行性的核心在于将数据有策略地分布至多个物理磁盘,实现多通道并发数据访问,从而极大提升I/O带宽和吞吐能力。在大规模数据环境下,通过并发加载/卸载数据,可有效缓解单磁盘I/O瓶颈,充分释放底层硬件的并行能力。
常见的数据分区策略包括轮询分区、哈希分区与范围分区,各自对应不同的应用需求和性能取向:
轮询分区采用循环分配策略,将数据记录依次分布在所有磁盘上。例如,对于一张包含100万条记录的学生信息表,假定有4块磁盘,系统将第1条记录写入磁盘0,第2条写入磁盘1,第3条写入磁盘2,第4条写入磁盘3,第5条重新分配至磁盘0,以此类推。该策略实现了高度均匀的数据分布,最大化I/O资源的并发利用,有利于大规模顺序扫描和批量处理场景。
哈希分区基于选定分区属性(如主键、用户ID等)施加哈希函数,按照哈希值将数据映射至不同的存储目标。以学生信息为例,可针对学号(学生ID)执行哈希计算:
|# 假设学生ID为202301001,哈希函数返回值为2 student_id = 202301001 hash_value = hash_function(student_id) % 4 # 结果为2 # 该学生记录存储在磁盘2上
哈希分区的最大优势是能够快速定位特定记录。当我们需要查找学生ID为202301001的记录时,只需要计算哈希值,直接访问对应的磁盘即可,而不需要搜索所有磁盘。
哈希分区特别适合点查询操作,例如“查找特定学生的成绩记录”。但对于范围查询(如“查找成绩在80-90分之间的所有学生”),哈希分区可能需要搜索所有磁盘。
范围分区根据属性值的范围来分配数据。假设我们按照学生的入学年份进行范围分区:
范围分区的优势在于能够高效处理范围查询。如果我们要查询2022年入学的所有学生信息,系统只需要访问磁盘2,大大提高了查询效率。
不同的分区策略在处理不同类型的查询时表现各异:
对于全表扫描操作,轮询分区表现最佳,因为它能够确保所有磁盘的负载均衡,实现真正的并行读取。
对于点查询(查找特定值的记录),哈希分区是最优选择。通过哈希函数,我们可以直接定位到目标磁盘,避免了不必要的磁盘访问。
对于范围查询,范围分区具有明显优势。例如,查询"2021年到2022年入学的学生"时,系统只需要访问磁盘1和磁盘2,而不需要搜索所有磁盘。
在实际的并行数据库系统设计与实现过程中,数据倾斜是影响系统性能与资源利用率的关键问题之一。当某一分区由于数据分布的不均匀,承载的数据量远超其他分区时,会导致对应存储节点或处理器成为系统瓶颈。 例如,若2022年入学学生数量异常增多(如因政策变化导致该年数据量为其他年份5倍),则以年份为分区键的范围分区将导致2022年区段的存储节点负载过高,其它节点资源则被闲置。
数据倾斜会显著削弱并行处理系统的性能提升上限。即使部署了10个并发处理器,如果单个处理器长期占据80%的负荷,系统整体的吞吐能力将受限于该节点。
针对数据倾斜问题,业界通常采取如下优化策略:
这些方法可以有效缓解因数据倾斜带来的资源浪费和性能瓶颈。

查询内并行性指的是在单条查询语句的执行过程中,调度多个处理器或多核资源以协同完成该查询的各个算子处理任务。其目标在于缩短响应延迟、提升吞吐能力,尤其适用于需要进行大规模数据处理的复杂OLAP查询。 相比之下,查询间并行性虽可提升系统整体吞吐,但对于单条长事务的加速作用有限。 查询内并行性的实现主要可分为两大类:
操作内并行性指将单一关系代数操作(如投影、选择、排序、连接等)内部细分为更小的逻辑分区,并分配到多个处理节点上并发执行。考虑大表排序等IO密集型或CPU密集型算子时,该模式能极大释放并行潜力,显著压缩单算子执行时延。
以全表排序为例:假设有一张包含1000万条学生成绩记录的表,按照“分数”字段分布于4个物理磁盘上。若对该表做全局排序,常见的操作内并行实现方案如下:
系统首先对数据集按排序关键字(分数)全局划分分区边界。例如指定分区向量[60, 75, 90],则分割规则如下:
每个处理器在接收到属于自己分区的数据后,独立进行本地排序。由于分区的特性,处理器1的所有数据都小于处理器2的数据,处理器2的数据又都小于处理器3的数据,以此类推。最终合并时,只需要将各处理器的结果按顺序连接即可,无需额外的合并操作。
每个处理器首先对其本地数据进行排序,然后系统使用相同的分区向量将每个处理器的已排序数据重新分区,并以排序的方式发送给目标处理器。 每个接收处理器对收到的多个已排序流进行归并操作,产生最终的排序结果。
操作间并行性一般分为流水线并行与独立并行两种典型类型。
流水线并行机制支持查询执行计划中的不同算子(如连接、投影、选择等)在多处理器资源上并发调度、重叠执行。通过算子间数据流的实时传递,上游操作产生的数据可直接输送至下游操作,无需物化中间结果。以四表连接为例:
|-- 查询学生、课程、成绩和教师信息 SELECT s.name, c.course_name, sc.score, t.teacher_name FROM students s JOIN student_courses sc ON s.student_id = sc.student_id JOIN courses c ON sc.course_id = c.course_id JOIN
在流水线并行中:
每个处理器可以在接收到部分中间结果时就开始处理,而不需要等待前一个操作完全结束。这种方式减少了中间结果的存储开销,提高了整体效率。
独立并行允许查询中互不依赖的操作同时执行。在上面的例子中,我们可以同时计算:
当这两个连接操作完成后,再计算:
这种并行方式特别适合复杂的查询树,其中存在多个可以并行执行的子查询。
连接操作是数据库查询中最耗时的操作之一,因此连接的并行化对提升查询性能至关重要。
分区连接适用于等值连接和自然连接。基本思想是将两个待连接的关系按照连接属性进行相同的分区,然后在每个处理器上独立计算本地连接。 假设我们要连接学生表(students)和成绩表(scores),连接条件是student_id相等:
由于使用了相同的哈希函数进行分区,具有相同student_id的记录一定会分配到相同的处理器上。这样,每个处理器只需要处理自己的分区数据,就能计算出完整的连接结果。
对于不等值连接(如学生年龄 < 教师年龄),分区连接方法不再适用,因为可能任意一个学生记录都需要与任意一个教师记录进行比较。 分片复制连接的解决方案是:将一个关系进行分区,将另一个关系复制到所有处理器上。例如,如果教师表相对较小,我们可以:
这种方法虽然增加了存储和网络开销,但它可以处理任意类型的连接条件。
并行查询的执行时间可以用以下公式估算:
|总执行时间 = 分区时间 + 结果汇总时间 + max(处理器1时间, 处理器2时间, ..., 处理器n时间)
理论上,若数据分布完全均匀且不存在额外开销,采用n个处理器并行执行可获得近似n倍的加速效果。然而在实际中,需综合考虑多种因素,包括多处理器启动操作所需的协调和通信成本、因数据分布不均造成的数据倾斜风险(可能导致部分处理器成为系统瓶颈)、内存、磁盘及网络资源的竞争带来的潜在延迟,以及在并行计算结束后对各处理器计算结果进行汇总和合并所产生的额外耗时,这些都可能使实际加速远低于理想值。
数据倾斜对并行性能的影响是致命的。即使只有一个处理器承担了过重的负载,整个查询的执行时间就会被这个“慢节点”所拖累。这就像木桶原理——木桶的容量由最短的木板决定。

在并行数据库环境中,查询优化的复杂性远超单处理器场景。并行查询优化器不仅须生成高效的执行计划,还需综合考虑操作的并行化粒度、调度策略以及多处理器间的资源协同与分配机制。 并行查询优化须应对如下几个技术难题:
鉴于最优并行计划空间过大与统计信息不完全等限制,现有主流系统普遍采用启发式算法,以降低优化复杂度:
此策略为每个查询算子分配所有可用处理器且避免流水线执行,简化资源调度和成本估算。其理念在于用最充分的硬件并行性压缩执行时间。Teradata即采用该模式:
该策略首先基于单处理器优化获得串行执行计划,然后通过插入特殊的交换算子来分解数据流与并行度,在局部/全局阶段灵活调整数据的分布和重分区。该模型由Volcano体系提出和推广,其核心思想为:
随着多核处理器的普及,数据库系统设计面临新的机遇和挑战。现代处理器不再追求单核性能的极限提升,而是通过增加核心数量来提高整体计算能力。

多核处理器的出现主要源于物理限制:更快的处理器需要更多的电能,这不仅增加了能耗和成本,还带来了散热问题。因此,处理器设计转向了“多核心”的方向。 现代多核处理器通常包含多级缓存结构:
L1缓存速度最快但容量最小,L2缓存次之,L3缓存容量较大但速度相对较慢。当处理器需要的数据不在缓存中时,就会发生缓存未命中(cache miss),需要从更慢的存储层级获取数据。
为了充分利用多核处理器的能力,现代系统广泛采用多线程技术。每个核心可以支持多个硬件线程,当一个线程因为缓存未命中而等待时,核心可以切换到另一个线程继续执行。 例如,Sun UltraSPARC T2处理器有8个核心,每个核心支持8个线程,总共可以同时执行64个线程。
虽然数据库系统天然适合利用并行性(因为支持大量并发事务),但在现代多核环境中充分发挥性能仍面临挑战:
现代数据库系统正在探索新的架构模式,例如将单个查询的处理分解为多个阶段的流水线,或者寻找有效的方法来并行化单个数据库操作,以更好地利用多核处理器的计算能力。