Vertica 集群 Rebalance 完全指南¶
编译:JiangChong
综合翻译整理自 Vertica Knowledge Base 三篇文章:
- Best Practices for Preparing Your Cluster for Rebalance(Rakesh Bankula & Soniya Shah 合著)
- Understanding Rebalancing, Part 1: What Happens During Rebalancing
- Understanding Rebalancing, Part 2: Optimizing for Rebalancing
📝 文章说明:原文三篇 KB 文章均基于 Enterprise 模式编写,讨论了数据重分布(data redistribution)的完整流程——内部原理、准备、执行监控、验证、耗时估算。原文未涉及 Eon 模式的 rebalance 机制。译者根据 Vertica v26.2 官方文档及 vault 中已有技术笔记,补充了 Eon 模式下的三种重平衡机制:
REBALANCE_SHARDS()(分片订阅再平衡)、RESHARD_DATABASE()(重新分片)、Elastic Crunch Scaling(弹性压缩伸缩),以及完整的 Enterprise vs Eon 对比表和决策框架。新增内容位于「第七部分」。
前言¶
在 Enterprise 模式下,增删节点后必须执行 REBALANCE_CLUSTER() 来重分布数据。这是一个 CPU、磁盘和网络密集型的复杂过程,涉及大量数据在节点间迁移,可能耗时数小时到数十小时。而在 Eon 模式下,增删节点通过 REBALANCE_SHARDS() 调整分片订阅关系即可,不迁移数据,分钟级完成。
阅读指引:第一~六部分适用于 Enterprise 模式,第七部分适用于 Eon 模式。两种模式的 rebalance 机制有根本性不同,请确认你运行的是哪种模式后再阅读对应章节。
本文整合了 Vertica 官方三篇关于 rebalance 的核心文档,并补充了 Eon 模式下的分片再平衡机制,涵盖:Enterprise 模式的内部原理 → 准备工作 → 执行监控 → 事后验证 → 耗时估算,以及 Eon 模式的 REBALANCE_SHARDS / RESHARD_DATABASE / ECS 三种机制的完整闭环。
第一部分:Rebalance 内部原理(Enterprise 模式)¶
来源:Understanding Rebalancing, Part 1: What Happens During Rebalancing
适用范围:仅 Enterprise 模式。Eon 模式的数据分布原理见第七部分 §7.1。
在开始准备之前,先理解 rebalance 过程中到底发生了什么,这有助于你理解每项准备工作的意义。
1.1 何时需要 Rebalance¶
| 场景 | 说明 |
|---|---|
| 数据量增长 | 磁盘接近写满,需要增加节点扩容 |
| 分析负载增加 | 查询并发量或复杂度上升,现有节点 CPU/内存不足 |
| 提高 K-safety | 增加节点以提升高可用性(更多 buddy projection 副本) |
| 节点下线 | 缩容、硬件维护、升级替换(swap 不需要 rebalance) |
重要:Vertica 不允许在违反 K-safety 的前提下移除节点。例如 K-safety=1 时,如果移除某节点会导致部分数据只剩 0 个副本,操作将被拒绝。
1.2 数据如何移动¶
Rebalance 的核心目标:将数据从 N 个节点上各占 1/N 重新分布到 M 个节点上各占 1/M。Vertica 通过以下策略最小化数据移动量:
- 新节点插入位置经过优化:新节点不是简单追加到集群末尾,而是插入到能最小化数据迁移的位置
- 分段投影(segmented projection):原有节点上的 ROS container 被拆分(split),然后将相应的数据段转移到目标节点
- 非分段投影(unsegmented projection):直接从 buddy 节点完整复制到新节点,因为每个节点本身就存有全量副本
- rebalance 完成后:目标节点上的数据分段由 Tuple Mover 在下次 mergeout 时合并,这一步不属于 rebalance 本身
数据移动量取决于: - 集群原有节点数和新增/移除节点数 - 分段投影 vs 非分段投影的数量比例
示例(基于 Part 1 原文的 3→4 节点场景):每个节点从持有 1/3 数据变为持有 1/4 数据。Vertica 将新节点插入到数据迁移最少的位置,仅移动约 4/12(约 1/3)的总数据量——Node1 移出 1/12、Node2 移出 2/12、Node3 移出 1/12。对于 4→5 节点场景原理相同,移动比例类似。
磁盘空间不足时的级联 rebalance:如果现有节点剩余空间很少,Vertica 不得不分多阶段执行 rebalance:
- 第一阶段:将数据分布到新节点
- 第二阶段:数据从释放了空间的节点继续向其他节点迁移
- 后续阶段:重复上述过程直到平衡
每多一个阶段,总耗时大幅增长。这解释了为什么确保 40% 以上空闲空间至关重要。
1.3 REFRESH 资源池¶
Rebalance 始终使用内置的 REFRESH 资源池(不是 General pool,也不是用户自定义 pool)。
| 参数 | 说明 |
|---|---|
PLANNEDCONCURRENCY |
控制同时 rebalance 的 projection buddy group 数量。这是唯一有效的并发控制参数 |
MAXCONCURRENCY |
对 REFRESH 资源池无效(官方文档明确说明) |
建议:优先使用默认设置,不要随意调大
PLANNEDCONCURRENCY,过高的并发可能导致 I/O 争抢反而拖慢进度。
1.4 Rebalance 的四个阶段¶
阶段一:插入新节点¶
Vertica 将新节点插入到数据迁移最小的位置。对于大规模集群,插入位置对性能影响显著。
阶段二:数据重分段(Resegmenting)¶
这是 rebalance 最耗时的阶段,最多可占总耗时的 80%。
对非分段投影(unsegmented projection):
- 对每个 projection 获取 X 锁(排他锁)
- 在新节点上执行
CREATE PROJECTION ... UNSEGMENTED ALL NODES KSAFE - 从 buddy projection 刷新数据
对分段投影(segmented projection):
- 对表获取 S 锁(共享锁),对 projection 获取 X 锁(排他锁)
- 分离 primary、buddy、live aggregate projection 的数据段
- 刷新 projection
重分段过程需要临时存储空间作为分段数据的暂存区,因此 Vertica 每次只处理少量表和 projection,以高效利用临时空间。
阶段三:数据传输(Transferring)¶
Vertica 使用哈希函数决定数据在节点间的分布。
- 非分段投影传输:源节点读数据,目标节点写数据。多个源节点可以并行向多个目标节点传输,CPU 开销很小
- 分段投影传输:源节点需要完成读、拆分、写三个步骤,需要时间和临时磁盘空间。这一步最消耗资源
阶段四:数据合并(Merging)¶
这一步不属于 rebalance 过程本身。Rebalance 完成后,Tuple Mover 在下次 mergeout 时将目标节点上的数据片段合并。如果有 ephemeral 节点(缩容场景),Vertica 会在此阶段删除不再需要的非分段投影。
1.5 影响 Rebalance 耗时的因素¶
| 因素 | 影响 |
|---|---|
| Projection 数量 | 每个 projection 都要独立处理,数量越多越慢 |
| 每张表的分区数 | 分区越多,ROS container 越多 |
| 数据量和行数 | 直接影响 split 和 transfer 的数据量 |
| 目标节点上的 merge 时间 | 取决于 Tuple Mover 的后续 mergeout |
| 最繁忙节点的读写总量 | 决定了整体耗时下限 |
| 数据倾斜 | 倾斜越严重,某些节点需要移动的数据越多 |
| 网络吞吐 | 1Gbps vs 10Gbps,传输时间差一个数量级 |
| I/O 瓶颈 vs 网络瓶颈 | 取决于集群的硬件瓶颈在哪 |
| 集群上的其他负载 | ETL、用户查询抢占资源 |
关键认知:分段投影的 resegment 和 ROS container split 可占 总耗时的 80%。这就是为什么准备工作要围绕「减少 ROS 数量」和「加速 split」展开。
第二部分:准备工作(Enterprise 模式)¶
来源:Best Practices for Preparing Your Cluster for Rebalance + Understanding Rebalancing Part 1 & 2
适用范围:仅 Enterprise 模式。Eon 模式增删节点无需本节所述的准备工作,直接跳至第七部分。
分为「必须执行」和「强烈推荐」两类。
2.1 必须执行的操作¶
① 清理无用的数据库对象¶
Rebalance 耗时与数据库中的对象数量强相关。每个 projection、每个 ROS container 都需要参与 rebalance。
删除冗余 schema 和表:已废弃但未删除的表仍占用对象计数。
检查并删除冗余 projection:一张表上可能有多个 projection(不同排序键、分段键用于优化不同查询),但并非越多越好。每个 projection 都需要独立完成 ROS split 和 transfer。
-- 查看每张表的 projection 数量
SELECT projection_schema, anchor_table_name, count(distinct projection_name) proj_count
FROM projections
GROUP BY 1, 2
ORDER BY 3 DESC;
proj_count 特别高的表值得审视——super projection 是基础投影,其他多为 live aggregate projection 或 top-K projection。如果某些查询场景已不再使用,对应的 projection 可以删除。
清理历史分区:事实表通常按时间分区,过期分区如果不再需要查询,其中的 ROS container 仍在 storage_containers 中。
-- 查看分区数异常多的表
SELECT table_schema, projection_name, count(distinct partition_key) partition_count
FROM partitions
GROUP BY 1, 2
ORDER BY 3 DESC;
可用 DROP_PARTITION 或 MOVE_PARTITIONS_TO_TABLE 清理不再需要的分区。
② 推进 AHM 并清理删除记录¶
Vertica 使用 MVCC(多版本并发控制),DELETE 操作不物理删除数据,仅标记为删除。这些记录直到 AHM(Ancient History Mark)推进后、Tuple Mover mergeout 时才真正清除。
如果 AHM 滞后于 current_epoch 太多,rebalance 中 split ROS container 时将触发 replay delete(重放历史删除操作),对 CPU 和 I/O 造成沉重负担。
-- 第一步:推进 AHM 到最近的 epoch
SELECT make_ahm_now();
-- 第二步:验证 AHM 是否接近 current_epoch(相差 1 以内理想)
SELECT get_ahm_epoch(), get_last_good_epoch(), get_current_epoch();
确认 AHM 已推进后,对事实表(尤其是存在数百万条已删除记录的表)执行 PURGE:
⚠️
PURGE物理删除已标记删除的记录,一旦执行无法回滚。务必确认备份可用。
③ 关闭 Rebalance 期间的磁盘空间检查¶
Rebalance 过程中 Vertica 多次查询 storage_containers 来确定 projection 的 rebalance 顺序(避免中间状态写满磁盘)。对于拥有数十万 ROS container 的数据库,单次查询可能耗时数分钟,多次重复累计可超过数小时。
如果你的集群磁盘空间充足(远未达到容量上限),可以关闭此检查:
低于此版本建议先升级再执行 rebalance。
关于磁盘空间的定量建议:Part 1 文档建议至少保留数据库大小的 40% 作为空闲空间。如果低于此阈值,Vertica 会进入多阶段 rebalance,耗时显著增加。可以用以下方式确认:
-- 检查各节点磁盘使用情况
SELECT host_name, disk_space_used_mb, disk_space_total_mb
FROM host_resources;
-- 更细粒度的存储信息(也可查看 DISK_STORAGE / COLUMN_STORAGE 系统表)
SELECT node_name, projection_name, used_bytes
FROM projection_storage;
④ 调整资源池配置¶
-- 查看当前 REFRESH 资源池配置
SELECT name, is_internal, plannedconcurrency, maxmemorysize
FROM resource_pools
WHERE name = 'REFRESH';
建议将 PLANNEDCONCURRENCY 设为与单节点 CPU 核数相同,以便 rebalance 的 ROS split 操作能充分利用 CPU 并行度。
如果在维护窗口执行 rebalance,临时释放用户自定义资源池占用的内存:
rebalance 完成后恢复原值。
⑤ 新增节点硬件和系统验证¶
如果是扩容场景,新节点配置必须不低于现有节点:
| 检查项 | 工具 | 说明 |
|---|---|---|
| 磁盘 I/O | vioperf |
直接决定 ROS split 和 transfer 的 IO 吞吐 |
| 网络吞吐 | vnetperf |
决定 ROS transfer 阶段的传输速度 |
| CPU | vcuperf |
决定 ROS split 时的并行计算能力 |
| OS 参数 | 对比 sysctl、limits.conf 等 | 内存锁定、文件句柄、网络缓冲区必须一致 |
新节点性能低于现有节点 → rebalance 以最慢节点为瓶颈 → 日常查询性能也退化。
⑥ 禁用本地分段¶
在执行 rebalance 之前,必须禁用 local segmentation:
Local segmentation 默认是禁用的,但建议在操作前确认。
⑦ 验证 Rebalance 成功¶
成功时返回 节点数 + 1 行。例如 10 节点集群返回 11 行,每行包含 10 个 1 或 0。行数异常或数值异常说明 rebalance 未完全成功。
2.2 强烈推荐的操作¶
① 升级 Vertica 版本¶
使用 Vertica 8.0.1 以下版本建议先升级。新版本改进:
- ROS split 并行度提升(多线程处理不同尺寸范围的 ROS)
rebalance_table_status和rebalance_projection_status监控表效率优化- Vertica 8.0 新增
rebalance_operations系统表,可按操作步骤实时追踪进度
② 执行全量备份¶
增删节点和 rebalance 是对集群的重大变更。尽管 rebalance 自身可失败回滚,但硬件故障、磁盘满、网络中断等极端情况仍可能导致数据丢失。
③ 在维护窗口中执行¶
理想情况下应完全停止:
- ETL / 数据加载(COPY 语句创建新 ROS,干扰 split 执行计划)
- UPDATE / DELETE(产生新 delete vector)
- 所有用户查询(抢占 CPU、内存、磁盘 I/O)
如果无法独占窗口,至少做到最小化 DML 操作,只保留必要的 SELECT 查询。
④ 重启数据库¶
长时间运行的数据库 catalog 持续膨胀,拖慢 catalog 更新操作。重启后 catalog 完全加载到内存并重新组织,读写效率显著提升。
第三部分:执行与监控(Enterprise 模式)¶
来源:Understanding Rebalancing, Part 2: Optimizing for Rebalancing
适用范围:仅 Enterprise 模式。Eon 模式监控方法见第七部分 §7.6。
3.1 启动 Rebalance¶
有三种方式:
| 方式 | 说明 |
|---|---|
| admintools UI | 图形界面操作 |
| Management Console (MC) | Web 管理控制台 |
| SQL 函数 | SELECT REBALANCE_CLUSTER();(最灵活) |
SQL 方式适合脚本化和自动化场景。注意:全局只能有一个 rebalance 操作在运行。
3.2 监控查询大全¶
以下查询可在 rebalance 执行期间随时运行,帮助判断进度和发现问题。
当前正在 rebalance 的表¶
如果 DML/DDL 操作干扰了 rebalance,会看到:
当前活跃的 rebalance 操作¶
SELECT node_name, session_id, session_start_timestamp, description
FROM system_sessions
WHERE session_type = 'REBALANCE_CLUSTER'
AND is_active;
通过 session_start_timestamp 可以了解 rebalance 已运行了多久。
整体进度概览¶
SELECT rebalance_method AS Rebalance_method,
Status,
COUNT(*) AS Count
FROM (
SELECT rebalance_method,
CASE
WHEN (separated_percent = 100 AND transferred_percent = 100)
THEN 'Completed'
WHEN (separated_percent <> 0 AND separated_percent <> 100)
OR (transferred_percent <> 0 AND transferred_percent <> 100)
THEN 'In Progress'
ELSE 'Queued'
END AS Status
FROM rebalance_projection_status
WHERE is_latest
) AS tab
GROUP BY 1, 2
ORDER BY 1, 2;
结果示例:
| Rebalance_method | Status | Count |
|---|---|---|
| ELASTIC_CLUSTER | Completed | 8 |
| ELASTIC_CLUSTER | In Progress | 2 |
| ELASTIC_CLUSTER | Queued | 2 |
| REPLICATE | Completed | 50 |
ELASTIC_CLUSTER= 分段投影的 rebalanceREPLICATE= 非分段投影的复制REFRESH= 投影刷新
非分段投影的刷新进度¶
SELECT session_id, projection_name, refresh_status, refresh_method, refresh_phase
FROM projection_refreshes
WHERE refresh_method = 'rebalance'
AND is_executing;
refresh_phase 可能值:
current:正在刷新当前数据historical:正在刷新历史数据
分段投影的分离和传输进度¶
SELECT projection_name, rebalance_method, separated_percent, transferred_percent
FROM rebalance_projection_status
WHERE rebalance_method = 'ELASTIC_CLUSTER'
AND ((separated_percent <> 0 AND separated_percent <> 100)
OR (transferred_percent <> 0 AND transferred_percent <> 100))
AND is_latest;
separated_percent:ROS container 已分离的百分比
transferred_percent:已传输到目标节点的百分比
Tuple Mover 正在执行分离操作¶
SELECT TM.projection_name, TM.node_name, TM.operation_start_timestamp
FROM tuple_mover_operations TM
JOIN system_sessions USING (session_id)
WHERE system_sessions.is_active
AND session_type = 'REBALANCE_CLUSTER'
AND operation_status = 'Running';
ROS Container 创建/删除统计¶
SELECT CASE
WHEN is_destroyed THEN 'deleted'
ELSE 'created'
END AS container,
projection_name,
SUM(row_count) AS rows_processed,
COUNT(*) n_containers
FROM vs_rebalance_separated_storage_containers
GROUP BY 1, 2
ORDER BY 1, 2;
数据传输详情¶
SELECT projection_name,
from_node_name,
to_node_name,
SUM(row_count) AS rows_transferred,
SUM(size_in_bytes) AS bytes_transferred
FROM vs_rebalance_transferred_storage_containers
GROUP BY 1, 2, 3
ORDER BY 1, 2, 3;
每个 Projection 的 Rebalance 耗时¶
SELECT node_name, projection_schema, projection_name,
start_time,
time - start_time AS duration
FROM dc_rebalanced_projections
ORDER BY 5 DESC;
可以帮助你识别哪些 projection 是耗时大户。
3.3 锁竞争处理¶
如果在 ETL 作业运行期间执行 rebalance,可能出现锁竞争,导致 ETL 作业或 rebalance 操作失败。
哪些操作会与 rebalance 竞争锁:
DELETEUPDATEDROP_PARTITIONSWAP_PARTITION_BETWEEN_TABLESMOVE_PARTITION_TO_TABLE
三种应对策略:
策略一:调整 LockTimeout¶
LockTimeout 参数决定 ETL 作业等待锁释放的超时时间,默认 300 秒(5 分钟)。如果 ETL 作业超时则报错退出。
先查看哪些事务曾经持锁超过 5 分钟:
SELECT DATE_TRUNC('hour', grant_time), node_name,
COUNT(*) number_of_tx,
MAX(time - grant_time) max_time_lock_held
FROM dc_lock_releases
WHERE time - grant_time > '5 min'
AND mode IN ('X', 'S', 'O')
AND object_name NOT LIKE 'ElasticCluster'
GROUP BY 1, 2
ORDER BY 4 DESC;
精确定位具体锁竞争的事务和 SQL 请求:
\x
SELECT t2.time, t2.node_name, t2.grant_time, t2.mode,
t2.object_name, t2."time" - t2.grant_time AS lockheld,
(t2."time" - t2.grant_time) * 1000 AS millisecond,
t3.request
FROM dc_lock_releases t2
JOIN query_requests t3 ON t2.transaction_id = t3.transaction_id
AND t2.statement_id = t3.statement_id
WHERE t2."time" - t2.grant_time > '5 min'
AND t2.mode IN ('X', 'S', 'O')
AND t2.object_name NOT LIKE 'ElasticCluster'
ORDER BY millisecond DESC;
\x
加大 LockTimeout:
-- 查看当前值
SELECT GET_CONFIG_PARAMETER('LockTimeout');
-- 默认 300 秒
-- 调大到 600 秒
SELECT SET_CONFIG_PARAMETER('LockTimeout', 600);
rebalance 完成后记得恢复原值!
策略二:优先保障 Rebalance(设置 DMLCancelTM)¶
默认情况下,如果 DML 作业试图访问被 rebalance 锁定的表,DML 作业会抢占锁并取消 rebalance,5 分钟后 rebalance 重新尝试。
如果希望 rebalance 不受干扰完成,设置:
-- 禁止 DML 抢占 rebalance 的锁
SELECT SET_CONFIG_PARAMETER('DMLCancelTM', false);
-- 执行 rebalance
SELECT REBALANCE_CLUSTER();
-- 完成后恢复
SELECT SET_CONFIG_PARAMETER('DMLCancelTM', true);
⚠️ 如果 DML 作业是关键业务(如实时数据加载),不要改
DMLCancelTM,而应该把 rebalance 安排在没有 DML 作业的时间窗口。
策略三:手动分批 Rebalance 大表¶
如果集群表非常多,一个维护窗口无法完成,可以每个窗口手动 rebalance 固定数量的表:
-- 单表 rebalance
SELECT REBALANCE_TABLE('schema.table_name');
-- 查看哪些表已完成/进行中/未开始
SELECT table_name,
CASE
WHEN separated_percent + transferred_percent = 200 THEN 'REBALANCED'
WHEN (separated_percent + transferred_percent) < 200
AND (separated_percent + transferred_percent) > 0 THEN 'REBALANCING'
ELSE 'NOT REBALANCED YET'
END AS status
FROM rebalance_table_status
WHERE is_latest;
手动 rebalance 时确保没有 ETL 作业在运行。
3.4 常见竞争错误¶
| 错误 | 原因 | 处理 |
|---|---|---|
ERROR 3007: DDL statement interfered with this statement |
其他作业对 rebalance 锁定的表执行了 DDL | 等待 DDL 完成或错开时间 |
ERROR 5157: Unavailable: lock table for query - Locking failure: Timed out |
获取锁超时 | 增大 LockTimeout 或错开负载 |
ERROR 7121: Staging table and target table do not match |
在两个 rebalance 状态不一致的表之间 SWAP PARTITION | 只允许两张都已 rebalance 或两张都未 rebalance 的表之间交换分区 |
Rebalance 失败后的重启机制:如果 rebalance 因错误失败或被 DML 取消,Vertica 会在 300 秒(5 分钟)后自动尝试重新运行。重要:一旦故障原因解决,rebalance 将从失败点继续执行,而不是从头开始。这避免了对已完成工作的重复浪费。
查询失败原因:
SELECT time, session_id, error_level, node_name, log_message
FROM dc_errors
WHERE session_id IN (
SELECT DISTINCT session_id
FROM dc_session_starts
WHERE session_type = 'REBALANCE_CLUSTER'
)
ORDER BY time DESC;
第四部分:完成后验证(Enterprise 模式)¶
来源:Understanding Rebalancing, Part 2: Optimizing for Rebalancing
适用范围:仅 Enterprise 模式。Eon 模式验证方法见第七部分 §7.6。
4.1 确认成功¶
返回行数 = 节点数 + 1 即成功。
4.2 检查 K-safety¶
确认 K-safety 与预期一致(通常为 1 或 2)。
4.3 清理过期的 Projection¶
如果 rebalance 失败后重试,可能留下过期的 projection,需手动清理:
SELECT projection_name, anchor_table_name, is_prejoin, is_up_to_date
FROM projections
WHERE is_up_to_date = FALSE;
对 is_up_to_date = FALSE 的 projection 执行 DROP PROJECTION。
4.4 建立新基线¶
Rebalance 完成后,在空闲时段运行 vioperf 和 vnetperf 建立新集群的性能基线,便于日后对比。
⚠️ 这些工具对系统性能影响显著,不要在 rebalance 期间运行。
第五部分:Rebalance 耗时估算(Enterprise 模式)¶
来源:Best Practices for Preparing Your Cluster for Rebalance
适用范围:仅 Enterprise 模式。Eon 模式的
REBALANCE_SHARDS()和RESHARD_DATABASE()为元数据操作,不涉及数据迁移,耗时估算方法完全不同(分钟级,主要取决于 catalog 大小)。
完整的 rebalance 生命周期包含四个阶段:
5.1 ROS Split 耗时估算¶
Split ROS container 的耗时等于同尺寸 ROS 的 mergeout 耗时(操作逻辑对称)。
公式:
计算示例(24 核,105,901 个 <1GB ROS + 94 个 1-2GB ROS):
关键洞察:小 ROS 数量决定了 split 耗时的主体部分。每个 ROS 的 split 操作有固定的启动开销(打开文件、解析元数据、初始化排序上下文),ROS 再多再小也得逐个处理。这也是为什么「清理无用对象」是准备工作中的第一优先级。
5.2 ROS Transfer 耗时估算¶
取决于网络带宽和每节点数据量。
示例(10Gbps,每节点 3TB,扩容 1 倍):
多线程并行、带宽共享、TCP 拥塞控制等因素使实际耗时落在 1-1.5 小时。如果是 1Gbps 网络,传输时间增长约 10 倍,成为瓶颈。
5.3 系统表查询¶
对于 50 万 ROS container 的数据库,单次 storage_containers 查询可能耗时 3-5 分钟。rebalance 过程中 10-20 次查询累计可达 1-2 小时。
优化:磁盘使用率低于 50-60% 时,设置 RebalanceQueryStorageContainers = 0 可安全跳过。
5.4 杂项操作¶
包括 catalog 更新、node dependencies 计算、projection 统计刷新、事务提交等。
根据对 250+ 客户 scrutinize 的分析,每个 projection 平均耗时约 250ms,单线程串行处理(catalog 更新必须独立以避免锁冲突)。
示例(30,000 个 projection):
这个阶段的耗时主要取决于 projection 总数,与硬件配置关系不大。
5.5 客户案例验证¶
某客户(v7.1.2-6,HP Gen8 24 核 256GB,10Gbps,每节点 2.1TB,36,000 个 projection)从 16 节点缩容至 11 节点(移除 5 个):
| 阶段 | 估算 | 实际 |
|---|---|---|
| ROS Split | ~8-9 小时 | — |
| ROS Transfer | ~1-1.5 小时 | — |
| 系统表查询 | ~1-2 小时 | — |
| 杂项操作 | ~2.5 小时 | — |
| 合计 | ~12.5-15 小时 | 13 小时 |
高度吻合。客户在无 ETL/用户查询的独占维护窗口中执行。
第六部分:附录(Enterprise 模式)¶
A. 各尺寸 ROS 平均 Mergeout / Split 耗时¶
基于 250+ 客户 scrutinize 统计(未采集本库数据时可作参考):
| 尺寸范围 | 代码 | 平均耗时 (秒) |
|---|---|---|
| < 100MB | A_Less_than_100MB |
0.844 |
| 100MB - 200MB | B_Between_100MB_to_200MB |
2.000 |
| 200MB - 400MB | C_Between_200MB_to_400MB |
6.833 |
| 400MB - 600MB | D_Between_400MB_to_600MB |
11.095 |
| 600MB - 800MB | E_Between_600MB_to_800MB |
13.000 |
| 800MB - 1GB | F_Between_800MB_to_1GB |
23.000 |
| 1GB - 2GB | G_Between_1GB_to_2GB |
35.000 |
| 2GB - 4GB | H_Between_2GB_to_4GB |
68.000 |
| 4GB - 8GB | I_Between_4GB_to_8GB |
137.846 |
| 8GB - 16GB | J_Between_8GB_to_16GB |
320.444 |
| 16GB - 32GB | K_Between_16GB_to_32GB |
617.650 |
| > 32GB | L_Greater_than_32GB |
2528.500 |
注意:ROS 大小与 split 耗时非线性。一个 32GB+ ROS 平均耗时 42 分钟,远超 32 个 1GB ROS 的总耗时(32 × 35 = 1120 秒 ≈ 19 分钟)。这说明过大的 ROS 对 rebalance 更加不利——Tuple Mover 的后台 mergeout 将小 ROS 合并的原因之一正是在寻找这个平衡点。
B. 精确估算脚本(可选)¶
如果需要从本库统计实际 mergeout 耗时(比附录 A 经验值更准确)。
B1. 创建 merge_time 表¶
填充数据(从 dc_tuple_mover_events 提取历史 mergeout 耗时):
INSERT INTO merge_time
SELECT ros_size, max(avg_duration) time_sec
FROM (
SELECT
s.node_name,
CASE
WHEN s.total_size_in_bytes < 100000000 THEN 'A_Less_than_100MB'
WHEN (s.total_size_in_bytes > 100000000
AND s.total_size_in_bytes < 200000000) THEN 'B_Between_100MB_to_200MB'
WHEN (s.total_size_in_bytes > 200000000
AND s.total_size_in_bytes < 400000000) THEN 'C_Between_200MB_to_400MB'
WHEN (s.total_size_in_bytes > 400000000
AND s.total_size_in_bytes < 600000000) THEN 'D_Between_400MB_to_600MB'
WHEN (s.total_size_in_bytes > 600000000
AND s.total_size_in_bytes < 800000000) THEN 'E_Between_600MB_to_800MB'
WHEN (s.total_size_in_bytes > 800000000
AND s.total_size_in_bytes < 1000000000) THEN 'F_Between_800MB_to_1GB'
WHEN (s.total_size_in_bytes > 1000000000
AND s.total_size_in_bytes < 2000000000) THEN 'G_Between_1GB_to_2GB'
WHEN (s.total_size_in_bytes > 2000000000
AND s.total_size_in_bytes < 4000000000) THEN 'H_Between_2GB_to_4GB'
WHEN (s.total_size_in_bytes > 4000000000
AND s.total_size_in_bytes < 8000000000) THEN 'I_Between_4GB_to_8GB'
WHEN (s.total_size_in_bytes > 8000000000
AND s.total_size_in_bytes < 16000000000) THEN 'J_Between_8GB_to_16GB'
WHEN (s.total_size_in_bytes > 16000000000
AND s.total_size_in_bytes < 32000000000) THEN 'K_Between_16GB_to_32GB'
ELSE 'L_Greater_than_32GB'
END AS ros_size,
avg(DATEDIFF(SECOND, s.time, c.time)) as avg_duration
FROM dc_tuple_mover_events s
JOIN dc_tuple_mover_events c
ON s.node_name = c.node_name
AND s.projection_oid = c.projection_oid
AND s.transaction_id = c.transaction_id
AND s.session_id = c.session_id
WHERE s.operation = 'Mergeout'
AND c.operation = 'Mergeout'
AND s.event = 'Start'
AND c.event = 'Complete'
AND s.container_count > 1
AND c.container_count > 1
AND s.transaction_id NOT IN (
SELECT DISTINCT transaction_id
FROM dc_tuple_mover_events
WHERE event ILIKE '%replay delete%'
)
GROUP BY 1, 2
) f
GROUP BY 1;
COMMIT;
关键过滤条件说明:
container_count > 1:只统计真正合并至少 2 个 ROS 的 mergeout,排除单 ROS resize/moveouttransaction_id NOT IN (... replay delete ...):排除涉及 replay delete 的 mergeout——这些操作的耗时包含了重放删除的开销,会高估纯 split 时间(前提是已按本文要求推进 AHM,split 阶段不会触发 replay delete)。此外该估算也不考虑与用户发起 purge 操作相关的 mergeout 操作- 如果
dc_tuple_mover_events历史数据不足(数据库刚启动),直接用附录 A 的经验值
B2. 创建 ros_count 表¶
CREATE TABLE public.ros_count (
ros_size varchar(25),
ros_count int
);
INSERT INTO ros_count
SELECT ros_size, max(ros_count) max_ros_cnt
FROM (
SELECT
node_name,
CASE
WHEN used_bytes < 100000000 THEN 'A_Less_than_100MB'
WHEN (used_bytes > 100000000
AND used_bytes < 200000000) THEN 'B_Between_100MB_to_200MB'
WHEN (used_bytes > 200000000
AND used_bytes < 400000000) THEN 'C_Between_200MB_to_400MB'
WHEN (used_bytes > 400000000
AND used_bytes < 600000000) THEN 'D_Between_400MB_to_600MB'
WHEN (used_bytes > 600000000
AND used_bytes < 800000000) THEN 'E_Between_600MB_to_800MB'
WHEN (used_bytes > 800000000
AND used_bytes < 1000000000) THEN 'F_Between_800MB_to_1GB'
WHEN (used_bytes > 1000000000
AND used_bytes < 2000000000) THEN 'G_Between_1GB_to_2GB'
WHEN (used_bytes > 2000000000
AND used_bytes < 4000000000) THEN 'H_Between_2GB_to_4GB'
WHEN (used_bytes > 4000000000
AND used_bytes < 8000000000) THEN 'I_Between_4GB_to_8GB'
WHEN (used_bytes > 8000000000
AND used_bytes < 16000000000) THEN 'J_Between_8GB_to_16GB'
WHEN (used_bytes > 16000000000
AND used_bytes < 32000000000) THEN 'K_Between_16GB_to_32GB'
ELSE 'L_Greater_than_32GB'
END AS ros_size,
COUNT(*) AS ros_count
FROM storage_containers
GROUP BY 1, 2
ORDER BY 1, 2
) f
GROUP BY 1;
COMMIT;
使用 max(ros_count) 取各节点中的最大值——基于最坏情况估算,因为 rebalance 期间所有节点同时进行 ROS split,耗时由 ROS 最多的节点决定。
B3. 计算最终预估¶
SELECT sum(duration_sec * ros_count) AS split_time_seconds
FROM merge_time m
JOIN ros_count r ON r.ros_size = m.ros_size;
结果单位秒,除以单节点 CPU 核数得到 ROS Split 阶段预估时间。加上 transfer、系统表查询、杂项操作三个阶段的估算即得总耗时。
第七部分:Eon 模式下的 Rebalance — 分片再平衡 vs 数据重分布¶
📝 补充说明:原文三篇 KB 文章仅讨论了 Enterprise 模式的 rebalance。然而 Vertica Eon 模式(存算分离架构)下的「rebalance」在本质上有根本性不同——它不迁移数据,只调整分片订阅关系。本章基于 Vertica v26.2 官方文档及 vault 中已有的 Eon 相关笔记,补充 Eon 模式下三种重平衡机制的完整指南。
7.1 架构差异:为什么 Eon 模式不需要数据 Rebalance¶
在 Enterprise 模式下,每个节点持有数据的一部分(通过 segmentation 分段分布)。添加节点 → 数据必须从 N 份重新分布到 M 份 → 这就是前面六个部分讨论的 REBALANCE_CLUSTER() 过程。
在 Eon 模式下,计算与存储分离:
- 数据存储在公共存储(S3 / MinIO / HDFS / Pure Storage FlashBlade),以 immutable 文件形式存在
- 节点不持有数据,只持有计算能力和本地 Depot 缓存
- 数据在创建时已按分片(Shard)预分段,分片是数据分布的逻辑单位
因此,Eon 模式的「rebalance」不移动任何数据文件。它只做一件事:调整节点对分片的订阅关系。新节点从公共存储读取其订阅分片的数据填充 Depot,而不是从其他节点接收数据。
| 维度 | Enterprise Rebalance | Eon Rebalance |
|---|---|---|
| 操作函数 | REBALANCE_CLUSTER() |
REBALANCE_SHARDS() |
| 操作对象 | 数据(ROS container 拆分+传输) | 分片订阅关系(元数据) |
| 数据移动 | 大量(TB 级数据在节点间传输) | 零(不移动数据文件) |
| 耗时级别 | 小时~天级 | 分钟级(元数据操作) |
| CPU/IO 密集 | 极高(ROS split 占 80% 耗时) | 极低(仅编录更新) |
| 数据库可用性 | DDL/DML 受限,通常需停服窗口 | 零停机(全程可读写) |
| 扩容准备 | 需要 40% 空闲磁盘、清理 ROS、AHM 推进 | 无需特殊准备 |
| 缩容 | rebalance 将数据迁走 → 移除节点 | 排空连接 → 自动重平衡分片 |
| 验证方式 | get_node_dependencies() |
node_subscriptions 查询 |
关键认知:如果你熟悉 Enterprise 的 rebalance,面对 Eon 模式时请忘记 ROS split、transfer、mergeout、scaling factor 这些概念——它们在 Eon 模式下完全不适用。
7.2 Eon Rebalance 的三种机制¶
Eon 模式有三种不同的「重平衡」操作,适用场景各不相同:
| 机制 | 函数 | 触发方式 | 适用场景 |
|---|---|---|---|
| 分片再平衡 | REBALANCE_SHARDS() |
手动(添加节点后必须) / 自动(移除节点时) | 子集群增删节点后重新分配分片订阅 |
| 重新分片 | RESHARD_DATABASE(N) |
手动,需全局 catalog 锁 | 改变分片数量以匹配节点规模 |
| 弹性压缩伸缩 | ECS(自动启用) | 自动(节点数 > 分片数时) | 同一分片多节点协作,无需手动触发 |
来源:Vertica 26.2.x Eon 模式文档 § Adding and removing nodes / § Reshard the default namespace / § Elastic crunch scaling
7.3 机制一:REBALANCE_SHARDS() — 分片订阅再平衡¶
原理¶
Eon 模式下每个分片(Shard)有对应的哈希范围(如 segment0001 覆盖 hash 0~1073741825)。节点通过订阅(Subscribe) 分片来声明自己负责处理该范围内的数据。
- K-safety=1 时,每个分片至少有 2 个订阅者(一个 primary,一个 secondary)
- 新节点加入子集群后初始没有任何分片订阅——此时新节点空闲,不参与查询
REBALANCE_SHARDS()将分片订阅均匀重新分配到子集群所有节点(含新节点),使各节点均匀分担
执行过程(从 node_subscription_change_phases 观察到的阶段):
COLLECT SHARD METADATA → 收集分片元数据
COLLECT SHARD METADATA WITH PLAN → 制定订阅分配计划
INSTALL SHARD METADATA LARGE → 安装大批量分片元数据
COLLECT SHARD METADATA WITH LOCK → 锁保护下收集增量元数据
INSTALL SHARD METADATA SMALL → 安装小批量增量元数据
COMMIT → 提交订阅变更
整个过程中,数据文件始终在原位(公共存储),节点只是更新了编录中的订阅元数据。这也是为什么 Eon rebalance 能分钟级完成。
操作步骤¶
添加节点到子集群后:
# 步骤1:将新节点添加到子集群
adminTools -t db_add_node -s 10.11.12.178 -d verticadb -p 'password' \
-c analytics_subcluster
-- 步骤2:确认新节点尚无分片订阅
SELECT subcluster_name, n.node_name, shard_name, subscription_state
FROM v_catalog.nodes n
LEFT JOIN v_catalog.node_subscriptions ns ON (n.node_name = ns.node_name)
ORDER BY 1, 2, 3;
-- 新节点的 shard_name 和 subscription_state 为空
-- 步骤3:手动执行分片再平衡(可指定子集群名称)
SELECT REBALANCE_SHARDS('analytics_subcluster');
-- 返回: REBALANCED SHARDS
-- 步骤4:验证新节点已获得分片订阅
SELECT subcluster_name, n.node_name, shard_name, subscription_state
FROM v_catalog.nodes n
LEFT JOIN v_catalog.node_subscriptions ns ON (n.node_name = ns.node_name)
ORDER BY 1, 2, 3;
-- 新节点现在应有 ACTIVE 状态的分片订阅
移除节点:Vertica 自动调用 REBALANCE_SHARDS(),无需手动执行。admintools -t db_remove_node 的内置流程就包含了分片再平衡,等待超时默认 36000 秒(10 小时)。
$ adminTools -t db_remove_node -p 'password' -d verticadb -s 10.11.12.117
Waiting for rebalance shards. We will wait for at most 36000 seconds.
来源:Vertica 26.2.x Eon 模式文档 § Updating shard subscriptions / § Removing nodes
移除 Primary 节点的特殊要求¶
移除主(Primary)子集群中的节点比移除 Secondary 子集群的节点更严格:
- 所有 Primary 节点必须处于 UP 状态
- 移除后数据库必须能维持 Quorum(半数以上 Primary 节点存活)
- 不满足条件时
REBALANCE_SHARDS会轮询等待(日志反复出现 "Rebalance shards polling iteration number [nn]")
7.4 机制二:RESHARD_DATABASE() — 改变分片数量¶
何时需要 Reshard¶
分片数量在创建数据库时确定,但以下场景可能需要调整:
| 场景 | 示例 | 目标 |
|---|---|---|
| 避免 ECS 低效 | 24 节点子集群 × 6 分片 → Reshard 到 24 分片 | 实现 1:1 节点:分片比,避免 ECS 开销 |
| Enterprise 迁移后优化 | 迁移后分片数=原 Enterprise 节点数,可能不理想 | 调整为更合理的数量 |
| 灵活扩缩容 | 7 分片 → 8 分片 | 8 的因数更多(2/4/8),子集群节点数选择更灵活 |
| 缩减编录大小 | 分片数过多导致编录膨胀 | 减少分片数以降低元数据开销 |
来源:Vertica 26.2.x Eon 模式文档 § Reshard the default namespace、Vertica Eon 模式中分片、节点和 Depot 选择的最佳实践
约束¶
- 只能对 default_namespace 操作,且必须是唯一的命名空间(有其他命名空间时报错)
- 原因:
RESHARD_DATABASE()只接受一个整数参数(新分片数),不接受 namespace 名称,隐含目标就是default_namespace。每个 namespace 有独立的分片数和 hash 边界,多 namespace 下只改default_namespace的分片会导致各 namespace 的 shard 边界不一致,而 Tuple Mover 的RESHARDMERGEOUT任务尚未支持按 namespace 区分处理。本质是 namespace(v24.1 引入)晚于RESHARD_DATABASE(),函数未被更新以处理多 namespace 场景。
- 原因:
- 获取全局 catalog 锁,避免在业务高峰期执行
- 不频繁操作:reshard 后存储容器不会立即对齐新分片边界,查询有额外过滤开销
多 Namespace 场景下的调整方案¶
如果环境中已存在多个 namespace 且需要调整分片数,当前版本(v26.2)的选项有限,本质是回退到单 namespace → 改 → 重建:
改 default_namespace 的分片数:
1. 备份非默认 namespace 中的数据(vbr 或导出)
2. DROP NAMESPACE(逐个删除非默认 namespace)
3. RESHARD_DATABASE(N) — 此时只剩 default_namespace,可以执行
4. 重新 CREATE NAMESPACE ... SHARD COUNT N(用新的分片数重建)
5. 恢复数据(vbr --target-namespace 或导出导入)
难点:ALTER TABLE ... SET SCHEMA 不能跨 namespace,表无法直接在 namespace 之间迁移。数据恢复需通过 vbr 指定 --target-namespace 或导出导入。
改非默认 namespace 的分片数:非默认 namespace 完全无法 reshard,只能创建新 namespace → 迁移数据 → 删除旧 namespace:
CREATE NAMESPACE airport_v2 SHARD COUNT 24;
-- 通过 vbr --target-namespace 或导出导入迁移数据
DROP NAMESPACE airport;
不改 shard 数,用节点数适配:如果无法改动 shard 数,反向让子集群节点数取各 namespace shard 数的公倍数。例如 default_namespace=6 shard、airport=8 shard → 子集群 24 节点(6 和 8 的最小公倍数),各 namespace 都能均匀分布。代价是可能接受 ECS 开销或节点资源冗余。
操作步骤与监控¶
-- 步骤1:查看当前分片数
SELECT * FROM NAMESPACES;
-- default_shard_count 列为当前分片数
-- 步骤2:查看当前分片边界
SELECT shard_name, lower_hash_bound, upper_hash_bound
FROM shards ORDER BY shard_name;
-- 步骤3:执行 Reshard(如 4→8)
SELECT RESHARD_DATABASE(8);
-- 步骤4:加速存储容器对齐(可选,需较新版本支持)
-- 支持 reshardmergeout 任务类型的版本中,可执行以下语句手动触发对齐;
-- 旧版本报 "not a known TM task" 则跳过,TM 后台 mergeout 会自动逐步对齐
-- SELECT DO_TM_TASK('RESHARDMERGEOUT');
-- 步骤5:监控 Reshard 进度
SELECT node_name, running_status, old_shard_name,
old_shard_lower_bound, old_shard_upper_bound
FROM RESHARDING_EVENTS;
来源:Vertica 26.2.x Eon 模式文档 § Reshard the default namespace
Reshard 后的过渡期:存储容器边界暂时不对齐新分片,查询时节点需过滤不属于其分片的数据(有小幅查询开销)。Tuple Mover 的后台 mergeout 会逐步自动对齐。在支持 reshardmergeout 任务类型的版本中,可通过 DO_TM_TASK('RESHARDMERGEOUT') 加速对齐;旧版本中此任务不可用,等待 TM 自动对齐即可。
7.5 机制三:Elastic Crunch Scaling(ECS)— 节点数 > 分片数¶
当子集群中的节点数超过命名空间的分片数时,Vertica 自动启用 ECS,让多个节点协作处理同一分片的数据。
ECS 的两种策略¶
| 策略 | 行为 | 数据分段保留? | 适用场景 |
|---|---|---|---|
| IO_OPTIMIZED | 将分片的 ROS 容器列表划分给各订阅节点 | ❌ 不保留 | I/O 密集型查询(大表扫描) |
| COMPUTE_OPTIMIZED | 保留 segmentation,支持 local join | ✅ 保留 | 计算密集型查询(多表 JOIN) |
| AUTO(默认) | Vertica 自动选择 | — | 大多数场景 |
| NONE | 禁用 ECS,只使用分片的 primary 订阅节点 | — | 调试/对比测试 |
来源:Vertica 26.2.x 官方架构文档、Vertica 26.2.x Eon 模式文档 § Using elastic crunch scaling
ECS 的效率¶
ECS 虽然让所有节点参与查询,但效率低于 1:1 节点:分片比的原生配置。官方文档明确指出:
"ECS is not as efficient as having a 1:1 shard:node ratio."
最佳实践:
- 节点数最好是分片数的整数倍(如 6 分片 → 6/12/18 节点)
- 如果长期运行在节点数 > 分片数的状态,考虑
RESHARD_DATABASE()增加分片数 - 非整数倍时,部分节点订阅更多分片,成为查询瓶颈
查询是否使用了 ECS¶
-- 检查会话的分片订阅是否为 collaborating 模式
SELECT * FROM SESSION_SUBSCRIPTIONS;
-- is_collaborating = true 表示该会话正在使用 ECS
EXPLAIN 输出中也会看到提示:
7.6 Eon Rebalance 的监控¶
Eon 模式下,Enterprise rebalance 的监控 SQL(第三部分)大多不适用。以下是 Eon 专属监控方法:
检查分片订阅状态¶
-- 按子集群查看分片订阅分布
SELECT subcluster_name, subscription_state,
COUNT(DISTINCT n.node_name) AS nodes,
COUNT(DISTINCT shard_name) AS shards
FROM nodes n
LEFT JOIN node_subscriptions ns ON (n.node_name = ns.node_name)
WHERE subscription_state != 'ACTIVE'
GROUP BY 1, 2
ORDER BY 1, 2;
-- 理想情况:返回 0 行(所有订阅均为 ACTIVE)
监控 REBALANCE_SHARDS 执行进度¶
-- 查看分片订阅变更的阶段和耗时
SELECT session_id, action,
MIN(start_time) AS start_time,
MAX(end_time) AS end_time,
TIMESTAMPDIFF(mi, MIN(start_time), MAX(end_time)) AS duration_min
FROM node_subscription_change_phases
GROUP BY 1, 2
ORDER BY 3 DESC;
查看分片变更详情(含错误)¶
SELECT session_id, action, start_time,
subscription_change_type, subscriber_node_name,
shard_name, source_node_name,
num_objs_affected, phase_result
FROM node_subscription_change_phases
WHERE session_id = '<session_id>'
ORDER BY start_time;
Eon 模式下的节点依赖检查¶
get_node_dependencies() 在 Eon 模式下不可用。替代方案:通过 node_subscriptions 查询同一分片的订阅节点来确定依赖关系。
-- Eon 模式节点依赖检查
SELECT shard_name,
LISTAGG(node_name USING PARAMETERS max_length=10240)
FROM node_subscriptions
WHERE node_name IN (SELECT node_name FROM nodes WHERE is_primary)
GROUP BY 1
ORDER BY 1;
检查 Reshard 状态¶
SELECT node_name, running_status,
old_shard_name, old_shard_lower_bound, old_shard_upper_bound
FROM RESHARDING_EVENTS;
7.7 Enterprise vs Eon Rebalance 完整对比¶
| 维度 | Enterprise REBALANCE_CLUSTER() |
Eon REBALANCE_SHARDS() |
Eon RESHARD_DATABASE() |
|---|---|---|---|
| 操作对象 | 数据(ROS container) | 分片订阅元数据 | 分片定义+订阅元数据 |
| 数据移动 | TB 级 | 零 | 零 |
| 耗时级别 | 小时~天 | 分钟~数十分钟 | 分钟~数十分钟 |
| CPU/IO 密集 | 极高 | 极低 | 低 |
| 数据库可用性 | DDL/DML 受限 | 全程可读写 | 全程可读写(有过渡开销) |
| 全局 Catalog 锁 | 无(逐表处理) | 无 | 有 |
| 扩容后操作 | 自动(REBALANCE_CLUSTER) | 手动(添加节点后必须) | 无需(非扩容操作) |
| 缩容后操作 | 自动 rebalance | 自动 | 无需 |
| 前置准备 | 清理对象+推进AHM+40%空间+备份 | 无特殊要求 | 避免业务高峰期 |
| 进展监控 | rebalance_table_status 等 |
node_subscription_change_phases |
RESHARDING_EVENTS |
| 验证成功 | get_node_dependencies() |
node_subscriptions (all ACTIVE) |
NAMESPACES / SHARDS 查询 |
| 失败恢复 | 5 分钟后自动重试,断点续传 | 可重新执行 | 可重新执行 |
| 影响查询 | 锁竞争可能导致查询失败 | 无影响 | 过渡期小幅过滤开销 |
7.8 决策框架:选哪种 Rebalance¶
需要调整集群计算资源?
├── Enterprise 模式?
│ ├── 增删节点 → REBALANCE_CLUSTER()(本文第一~六部分)
│ └── 仅改变弹性伸缩因子 → SET_SCALING_FACTOR()
│
└── Eon 模式?
├── 添加节点到子集群?
│ └── REBALANCE_SHARDS('subcluster_name')(必须手动执行)
│
├── 移除节点?
│ └── admintools -t db_remove_node(自动 REBALANCE_SHARDS)
│
├── 节点数 > 分片数且长期运行?
│ └── 评估 RESHARD_DATABASE(N)(增加分片避免 ECS 低效)
│ └── 如果只是临时扩容,接受 ECS 即可
│
├── Enterprise 迁移到 Eon 后优化?
│ └── RESHARD_DATABASE(N)(分片数≠原节点数时考虑调整)
│
└── 查询性能问题,EXPLAIN 显示 ECS?
└── 检查节点数/分片数比例 → 非整数倍?→ RESHARD_DATABASE()
详细伸缩规划参见 Vertica 弹性伸缩功能介绍与配置,分片数量选择参见 Vertica Eon 模式中分片、节点和 Depot 选择的最佳实践。
总结¶
Vertica 集群的资源调整在两种模式下有根本性不同,选择正确的机制至关重要:
Enterprise 模式(本文第一~六部分):
- 准备阶段做减法:清理无用对象、推进 AHM 清理删除记录、关闭不必要的系统表检查——目标是减少 rebalance 需要处理的对象数量
- 资源配置对齐:确保 40% 以上空闲磁盘空间(避免多阶段 rebalance)、REFRESH pool 并发数合理、释放用户池抢占的内存
- 监控驱动决策:利用本文第三部分的 SQL 查询实时追踪进度,遇到了锁竞争用 LockTimeout / DMLCancelTM / 手动分批三种策略应对
- 事后验证闭环:
get_node_dependencies()确认成功、清理过期 projection、运行 vioperf/vnetperf 建立新基线
Eon 模式(本文第七部分):
- 无需数据迁移:
REBALANCE_SHARDS()只调整分片订阅关系,不移动数据文件,分钟级完成 - 添加节点后必须手动执行:新节点初始无分片订阅,
REBALANCE_SHARDS()后才参与查询 - 移除节点自动处理:Vertica 自动重平衡分片,无需手动干预
- 分片数规划是核心:节点数最好是分片数的整数倍,否则触发 ECS(效率低于原生 1:1 比)
- Reshard 是战略操作:改变分片数需要全局 catalog 锁,避免频繁执行,规划好节点增长路径
参考¶
- Best Practices for Preparing Your Cluster for Rebalance
- Understanding Rebalancing, Part 1: What Happens During Rebalancing
- Understanding Rebalancing, Part 2: Optimizing for Rebalancing
扩展阅读¶
- Vertica 弹性伸缩功能介绍与配置 — Enterprise vs Eon 弹性伸缩的完整对比与实操
- K-Safety 最佳实践 — Eon 模式 Shard 订阅容错机制
- Vertica Eon 模式中分片、节点和 Depot 选择的最佳实践 — 分片数量规划与 Reshard 策略
- Eon双主子集群的注意事项 — 主子集群操作前必须降级
- NODE_SUBSCRIPTIONS — 分片订阅系统表字段说明
- NODE_SUBSCRIPTION_CHANGE_PHASES — 分片订阅变更阶段监控