跳转至

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:

  1. 第一阶段:将数据分布到新节点
  2. 第二阶段:数据从释放了空间的节点继续向其他节点迁移
  3. 后续阶段:重复上述过程直到平衡

每多一个阶段,总耗时大幅增长。这解释了为什么确保 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 projectiontop-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_PARTITIONMOVE_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

SELECT PURGE_TABLE('schema.fact_table_name');

⚠️ PURGE 物理删除已标记删除的记录,一旦执行无法回滚。务必确认备份可用。

③ 关闭 Rebalance 期间的磁盘空间检查

Rebalance 过程中 Vertica 多次查询 storage_containers 来确定 projection 的 rebalance 顺序(避免中间状态写满磁盘)。对于拥有数十万 ROS container 的数据库,单次查询可能耗时数分钟,多次重复累计可超过数小时。

如果你的集群磁盘空间充足(远未达到容量上限),可以关闭此检查:

-- Vertica 7.2.3-2 及以上版本支持
SELECT set_config_parameter('RebalanceQueryStorageContainers', 0);

低于此版本建议先升级再执行 rebalance。

关于磁盘空间的定量建议:Part 1 文档建议至少保留数据库大小的 40% 作为空闲空间。如果低于此阈值,Vertica 会进入多阶段 rebalance,耗时显著增加。可以用以下方式确认:

# Linux 级别检查各节点磁盘
df -h /vertica/data/
-- 检查各节点磁盘使用情况
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,临时释放用户自定义资源池占用的内存:

ALTER RESOURCE POOL <user_defined_pool> MEMORYSIZE '0%';

rebalance 完成后恢复原值。

⑤ 新增节点硬件和系统验证

如果是扩容场景,新节点配置必须不低于现有节点:

检查项 工具 说明
磁盘 I/O vioperf 直接决定 ROS split 和 transfer 的 IO 吞吐
网络吞吐 vnetperf 决定 ROS transfer 阶段的传输速度
CPU vcuperf 决定 ROS split 时的并行计算能力
OS 参数 对比 sysctl、limits.conf 等 内存锁定、文件句柄、网络缓冲区必须一致

新节点性能低于现有节点 → rebalance 以最慢节点为瓶颈 → 日常查询性能也退化。

⑥ 禁用本地分段

在执行 rebalance 之前,必须禁用 local segmentation:

SELECT DISABLE_LOCAL_SEGMENTS();

Local segmentation 默认是禁用的,但建议在操作前确认。

⑦ 验证 Rebalance 成功

SELECT get_node_dependencies();

成功时返回 节点数 + 1 行。例如 10 节点集群返回 11 行,每行包含 10 个 1 或 0。行数异常或数值异常说明 rebalance 未完全成功。

2.2 强烈推荐的操作

① 升级 Vertica 版本

使用 Vertica 8.0.1 以下版本建议先升级。新版本改进:

  • ROS split 并行度提升(多线程处理不同尺寸范围的 ROS)
  • rebalance_table_statusrebalance_projection_status 监控表效率优化
  • Vertica 8.0 新增 rebalance_operations 系统表,可按操作步骤实时追踪进度

② 执行全量备份

增删节点和 rebalance 是对集群的重大变更。尽管 rebalance 自身可失败回滚,但硬件故障、磁盘满、网络中断等极端情况仍可能导致数据丢失。

vbr backup --config-file /path/to/backup_config.ini

③ 在维护窗口中执行

理想情况下应完全停止

  • ETL / 数据加载(COPY 语句创建新 ROS,干扰 split 执行计划)
  • UPDATE / DELETE(产生新 delete vector)
  • 所有用户查询(抢占 CPU、内存、磁盘 I/O)

如果无法独占窗口,至少做到最小化 DML 操作,只保留必要的 SELECT 查询。

④ 重启数据库

长时间运行的数据库 catalog 持续膨胀,拖慢 catalog 更新操作。重启后 catalog 完全加载到内存并重新组织,读写效率显著提升。

admintools -t stop_db -d <dbname>
admintools -t start_db -d <dbname>

第三部分:执行与监控(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 的表

SELECT * FROM rebalance_table_status;

如果 DML/DDL 操作干扰了 rebalance,会看到:

ERROR 3007: DDL statement interfered with this statement

当前活跃的 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 = 分段投影的 rebalance
  • REPLICATE = 非分段投影的复制
  • 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 竞争锁

  • DELETE
  • UPDATE
  • DROP_PARTITION
  • SWAP_PARTITION_BETWEEN_TABLES
  • MOVE_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 LIST_SERVICES('TM');
-- Service: 'RebalanceCluster' is enabled, interval 300 second(s)

查询失败原因

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 确认成功

SELECT get_node_dependencies();

返回行数 = 节点数 + 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 完成后,在空闲时段运行 vioperfvnetperf 建立新集群的性能基线,便于日后对比。

⚠️ 这些工具对系统性能影响显著,不要在 rebalance 期间运行


第五部分:Rebalance 耗时估算(Enterprise 模式)

来源:Best Practices for Preparing Your Cluster for Rebalance

适用范围:仅 Enterprise 模式。Eon 模式的 REBALANCE_SHARDS()RESHARD_DATABASE() 为元数据操作,不涉及数据迁移,耗时估算方法完全不同(分钟级,主要取决于 catalog 大小)。

完整的 rebalance 生命周期包含四个阶段:

总耗时 = ROS Split + ROS Transfer + 系统表查询 + 杂项操作

5.1 ROS Split 耗时估算

Split ROS container 的耗时等于同尺寸 ROS 的 mergeout 耗时(操作逻辑对称)。

公式

ROS Split 耗时 = Σ(各尺寸 ROS 数量 × 该尺寸平均 mergeout 耗时) / 单节点 CPU 核数

计算示例(24 核,105,901 个 <1GB ROS + 94 个 1-2GB ROS):

= (105,901 × 9 + 94 × 18) / 24
= 954,801 / 24
= 39,783 秒 ≈ 11 小时

关键洞察:小 ROS 数量决定了 split 耗时的主体部分。每个 ROS 的 split 操作有固定的启动开销(打开文件、解析元数据、初始化排序上下文),ROS 再多再小也得逐个处理。这也是为什么「清理无用对象」是准备工作中的第一优先级。

5.2 ROS Transfer 耗时估算

取决于网络带宽和每节点数据量。

示例(10Gbps,每节点 3TB,扩容 1 倍):

传输量 ≈ 3TB × 50% = 1.5TB
耗时 ≈ 1.5TB / 900 MB/s ≈ 1,700 秒 ≈ 0.5 小时(单线程理想值)

多线程并行、带宽共享、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):

杂项耗时 ≈ 30,000 × 0.25 秒 = 7,500 秒 ≈ 2 小时

这个阶段的耗时主要取决于 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 表

CREATE TABLE merge_time (
    ros_size varchar(25),
    duration_sec float
);

填充数据(从 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/moveout
  • transaction_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,而不是从其他节点接收数据。

来源:Vertica 弹性伸缩功能介绍与配置Vertica 26.2.x 官方架构文档

维度 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                           → 提交订阅变更

来源:NODE_SUBSCRIPTION_CHANGE_PHASES

整个过程中,数据文件始终在原位(公共存储),节点只是更新了编录中的订阅元数据。这也是为什么 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]")

参见:Eon双主子集群的注意事项

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 输出中也会看到提示:

The execution of this query involves non-participating nodes. Crunch scaling

来源:Vertica 26.2.x Eon 模式文档

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;

来源:NODE_SUBSCRIPTION_CHANGE_PHASES

查看分片变更详情(含错误)

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 模式(本文第一~六部分):

  1. 准备阶段做减法:清理无用对象、推进 AHM 清理删除记录、关闭不必要的系统表检查——目标是减少 rebalance 需要处理的对象数量
  2. 资源配置对齐:确保 40% 以上空闲磁盘空间(避免多阶段 rebalance)、REFRESH pool 并发数合理、释放用户池抢占的内存
  3. 监控驱动决策:利用本文第三部分的 SQL 查询实时追踪进度,遇到了锁竞争用 LockTimeout / DMLCancelTM / 手动分批三种策略应对
  4. 事后验证闭环get_node_dependencies() 确认成功、清理过期 projection、运行 vioperf/vnetperf 建立新基线

Eon 模式(本文第七部分):

  1. 无需数据迁移REBALANCE_SHARDS() 只调整分片订阅关系,不移动数据文件,分钟级完成
  2. 添加节点后必须手动执行:新节点初始无分片订阅,REBALANCE_SHARDS() 后才参与查询
  3. 移除节点自动处理:Vertica 自动重平衡分片,无需手动干预
  4. 分片数规划是核心:节点数最好是分片数的整数倍,否则触发 ECS(效率低于原生 1:1 比)
  5. Reshard 是战略操作:改变分片数需要全局 catalog 锁,避免频繁执行,规划好节点增长路径

参考

扩展阅读