Redshift 的核心可以概括为:一个基于 PostgreSQL 代码库、但针对大规模数据分析进行了深度重构和优化的、全托管、列式存储、大规模并行处理的关系型数据仓库。

下面我们从几个核心技术维度来详细拆解它的实现。
核心架构:大规模并行处理
Redshift 的基石是 MPP 架构,与传统的单机数据库不同,MPP 将一个大的查询任务分解成多个小任务,分发到多个节点上并行执行,最后将结果汇总,从而极大地提升了查询性能。
架构组件:
-
Leader Node (领导节点):
(图片来源网络,侵删)- 职责: 这是整个集群的“大脑”,它不存储用户数据,也不执行计算。
- 接收和解析查询: 接收来自客户端的 SQL 查询。
- 查询编译和优化: 将 SQL 查询编译成优化的执行计划,这是 Redshift 智能的核心所在。
- 分发查询片段: 根据执行计划,将查询任务分解成多个片段,并分发到各个 Compute Node。
- 协调结果: 从各个 Compute Node 收集部分结果,进行聚合、排序等最终操作,然后将最终结果返回给客户端。
- 类比: 一个交响乐团的指挥家,他不需要演奏任何乐器,但他确保所有乐手(Compute Node)在正确的时机演奏正确的音符。
- 职责: 这是整个集群的“大脑”,它不存储用户数据,也不执行计算。
-
Compute Node (计算节点):
- 职责: 这是真正的“工人”,负责数据的存储和计算。
- 存储数据: 每个节点都存储一部分数据,数据根据 Distribution Key 分布在不同的节点上。
- 并行执行: 执行 Leader Node 分发的查询片段。
- 局部聚合/排序: 在自己的数据子集上进行聚合、排序等操作,然后将中间结果返回给 Leader Node。
- 规模: 你可以根据业务需求选择不同大小的节点(如
ra3.xlplus,ra3.4xlarge),并通过增加节点数量来线性扩展集群的计算和存储能力。
- 职责: 这是真正的“工人”,负责数据的存储和计算。
-
Node Interconnect (节点互联):
- 职责: 一个高速、低延迟的网络,专门用于 Leader Node 和 Compute Node 之间的通信。
- 技术: 早期版本使用自定义的 10GbE 网络,现代的 RA3 实例则使用更先进的 EFA (Elastic Fabric Adapter),提供了接近 HPC 集群的网络性能,确保数据在节点间高效流动。
存储引擎:列式存储
这是 Redshift 能够实现高性能分析查询的另一个核心,与传统数据库的行式存储(如 MySQL, PostgreSQL)不同,Redshift 采用列式存储。
行式存储 vs. 列式存储:

| 特性 | 行式存储 (OLTP - 事务处理) | 列式存储 (OLAP - 分析处理) |
|---|---|---|
| 数据组织 | 按行连续存储:(行1: ID, 姓名, 年龄), (行2: ID, 姓名, 年龄) |
按列连续存储:(ID列: 1, 2, 3), (姓名列: '张三', '李四', '王五'), (年龄列: 25, 30, 28) |
| 读取方式 | 读取一行数据时,需要读取该行所有列,非常适合按行读取的场景(如根据主键查单条记录)。 | 读取少数几列时,只需读取对应的列数据,极大减少 I/O,非常适合 SELECT COUNT(*), SELECT AVG(salary) 等分析查询。 |
| 压缩效率 | 同一列的数据类型相同,但值差异大,压缩率通常较低。 | 同一列的数据类型相同,且往往有大量重复值(如性别、国家、日期),压缩率极高。 |
| 适合场景 | 交易系统、在线应用 | 数据分析、报表、BI |
Redshift 的列式存储实现:
- 数据块: 数据在磁盘上被组织成固定大小的块(1MB),每个数据块内部,数据按列存储。
- 编码技术: Redshift 在列式存储的基础上,应用了多种编码技术来进一步减少存储空间和提高 I/O 效率。
- RUNLENGTH: 对连续重复的值进行编码(如 'M', 'M', 'M', 'F' -> 'Mx3, Fx1')。
- DELTA: 对数值型列,存储与前一个值的差值,而非绝对值。
- DICTIONARY Encoding: 为重复的字符串或短值创建一个字典,用 ID 代替原始字符串,节省空间。
- BYTEDICT: 类似字典编码,但更高效。
- AZ64: 一种高精度的整数压缩算法。
- 用户可以选择
AUTO编码,让 Redshift 自动为每列选择最优的编码方式。
查询处理与优化
Redshift 的查询优化器是其智能化的体现,它不是简单地执行 SQL,而是会进行一系列复杂的优化。
查询处理流程:
- 解析: Leader Node 解析 SQL 语法,生成语法树。
- 绑定: 检查表、列是否存在,进行类型检查。
- 优化: 这是最关键的一步。
- 基于成本的优化器: CBO 会根据表的统计信息(行数、列值的分布、数据大小等)来评估不同执行计划的成本,并选择成本最低的一个。
- 重写查询: 优化器可能会重写你的查询,例如将
JOIN顺序调整、将子查询转换为JOIN等,以获得更好的性能。 - 利用分布键和排序键: 优化器会优先利用你定义的 Distribution Key (分布键) 和 Sort Key (排序键) 来最小化数据在节点间的移动,这是 Redshift 性能调优的核心。
- 生成执行计划: 将优化后的逻辑计划转换成物理执行计划,即一系列具体的操作步骤。
- 分发与执行: Leader Node 将执行计划分发给 Compute Nodes。
- 结果汇总: Leader Node 收集并合并结果,返回给用户。
关键设计:分布键与排序键
这是 Redshift 性能调优的灵魂,直接决定了查询效率,理解它们的实现原理至关重要。
A. Distribution Key (分布键)
作用: 决定数据行如何分布在不同的 Compute Node 上。
三种分布方式:
-
KEY Distribution (键分布) - 默认且最常用
- 实现: 根据 Distribution Key 的值,通过哈希函数计算出哈希值,然后将数据行存储到对应哈希值的节点上。
- 目标: 保证相同 Key 的所有行都在同一个节点上。
- 优点:
- 极大优化 JOIN 操作: 当两个表使用相同的 Key 分布时,进行
JOIN操作时,只需要在对应的节点上进行本地JOIN,完全避免了数据在节点间的移动(称为Shuffle或Data Movement),性能提升巨大。
- 极大优化 JOIN 操作: 当两个表使用相同的 Key 分布时,进行
- 缺点:
- 数据倾斜: 如果某个 Key 的值特别多(一个热门的
category_id),会导致所有相关数据都集中在少数几个节点上,造成负载不均。
- 数据倾斜: 如果某个 Key 的值特别多(一个热门的
- 最佳实践: 将高频 JOIN 的列作为分布键,如果没有明显的 JOIN 列,选择一个高基数的列(即值多的列)作为分布键,以避免数据倾斜。
-
ALL Distribution (全分布)
- 实现: 每个表的所有数据行都完整地复制到每一个 Compute Node 上。
- 目标: 避免
Shuffle。 - 优点:
- 对于小表的
JOIN或GROUP BY性能极高,因为小表数据在每个节点都有副本,无需移动。 - 对于涉及小表的复杂聚合查询性能很好。
- 对于小表的
- 缺点:
- 存储空间消耗大: N 个节点,小表会被存储 N 份。
- 不适合大表: 大表会耗尽所有节点的存储空间。
- 最佳实践: 仅用于小表(例如维度表,小于几百万行)。
-
EVEN Distribution (偶分布)
- 实现: 数据行被均匀地、随机地分布到各个节点上,不考虑任何 Key。
- 目标: 保证每个节点的数据量大致相等。
- 优点:
保证数据在节点间的均匀分布。
- 缺点:
- 几乎总是导致
Shuffle。 任何需要跨节点操作的JOIN或 `GROUP BY
- 几乎总是导致
