ANALYZE和AUTO ANALYZE

更新时间:
复制为 MD 格式

本文档介绍HologresANALYZE命令,以及AUTO ANALYZE后台自动收集统计信息的行为,并对主要行为参数进行说明,便于您更清楚地了解和控制统计信息的收集行为,提高查询计划质量。

统计信息与 ANALYZE 概述

为什么需要统计信息?

优化器依赖表和列的统计信息来生成合理的执行计划,包括:

  • 行数、列数

  • 列宽度(Width)

  • 非重复值个数(Number of Distinct Values,NDV)

  • 最常见值(Most Common Values,MCV)及其频率

  • 直方图(Histogram)以及其他分布特征

这些信息将指导优化器:

  • 估算算子执行开销(Cost)

  • 裁剪执行计划搜索空间

  • 选择合适的 Join 顺序和 Join 算法

  • 估算内存和并行度

从而生成更优的执行计划。

ANALYZE 命令是用户主动收集表/列统计信息的标准手段。在缺乏统计信息或统计不准确时,查询计划可能明显退化,例如Join 顺序异常,进而表现为:Query发生OOM、执行时间长、实例CPU消耗高等。

AUTO ANALYZE 功能是Hologres系统自动收集表/列统计信息的标准方式。由于AUTO ANALYZE是后台异步的系统行为,从表的数据变化,到 AUTO ANALYZE 发现、调度、完成统计信息自动收集,是有二位数秒级~分钟级的延迟,因此在一些特殊场景下,推荐用户自行手动 ANALYZE,以确保统计信息被及时收集。

什么时候需要手动执行 ANALYZE

推荐在以下场景手动执行:

  • 表上执行了 INSERT / UPDATE / DELETE 操作,导入/更新/删除了大量数据之后,立即要被查询,推荐在INSERT / UPDATE / DELETE之后对表进行一次 ANALYZE;

  • 多表 Join 性能明显下降时,在关键 Join 列、Group By 列上执行列级 ANALYZE;

  • 执行外表的 CREATE FOREIGN TABLE 或者 IMPORT FOREIGN SCHEMA 后,立即要被查询,推荐查询前对新建外表执行一次 ANALYZE 收集初始统计;

  • 执行 CREATE EXTERNAL DATABASE 后,立即要被查询,推荐查询前对外部数据库下需要查询的表执行 ANALYZE;

  • 出现以下报错/表现之一:

    • 多表 Join OOM报错:Query executor exceeded total memory limitation ...,或者Query exceed per query memory limitation ...

    • 多表 Join 报错:Capacity error: BinaryArray cannot contain more than 2147483646 bytes ...

    • 导入或查询任务运行时间异常长且 CPU 使用率不均衡。

    • EXPLAIN <SQL> 发现某个Scan算子的行数预估为1000,-> Seq Scan on tbl (cost=0.00..5.00 rows=1000 width=1);说明表缺乏统计信息。

    • EXPLAIN <SQL> 发现某个Scan算子的行数预估为1,-> Seq Scan on tbl (cost=0.00..1.00 rows=1 width=1);说明表预估为0行,如果该Scan实际不为0行,则可能为统计信息过时,推荐进行一次手动 ANALYZE。

在上述场景中,通常建议先手动 ANALYZE 再观察是否恢复,再结合 AUTO ANALYZE 配置做进一步调优。

ANALYZE 命令

基本语法与行为

  • 收集整表所有列的统计信息

ANALYZE table_name;
  • 收集表行数,以及对表中所有普通列统一收集:Width、MCV、Histogram、NDV 等统计信息;

  • 采用基于采样的方式估算各类统计值,采样操作会在 ANALYZE 内部发起一个采样子SQL。

  • ANALYZE 默认从表中随机采样30000行,做统计信息收集与计算,不足30000行则全采。

  • 仅收集指定列的统计信息(推荐对关键列使用)

ANALYZE table_name(col1, col2, ...);
  • 对指定列额外计算更精确的 NDV(通常采用 APPROX_COUNT_DISTINCT 逻辑获得),较整表采样更准确,但开销更大;

  • MCV、Histogram、Width 等仍然通过采样获得;

  • 多次对同一列执行 ANALYZE 时,后一次会覆盖该列的旧统计信息,但不会影响其他未指定列。

对于具有多列的表,ANALYZE table_name; 不完全等价于 ANALYZE table_name(col1, col2, ...):后者在 NDV 上通常更精确,但代价更高。推荐对常用 Join 列、Group By 列等关键列执行列级 ANALYZE 作为补充。

限制与注意事项

  • 哪些列不会被 ANALYZE

    • 类型不支持:列类型为用户自定义类型(User Defined Type),或不在 Hologres 支持统计的类型集合内时,会跳过统计信息的收集:

      • 不支持 ANALYZE 的列类型包括:"char"(单字符类型),BIT,VARBIT,BYTEA,NAME,JSON,TSVECTOR,TSQUERY,OID,XID,CID,INET,POINT,LINE, LSEG,BOX,CIRCLE,PATH,POLYGON,BITARRAY,VARBITARRAY,BYTEAARRAY,INT2ARRAY,MONEYARRAY,NUMERICARRAY,TIMEARRAY,TIMETZARRAY,TIMESTAMPTZARRAY,TIMESTAMPARRAY,ANYARRAY,REGCLASS,DATEARRAY或其他INTERNAL类型。

      • 当列类型不支持时,无论手动 ANALYZE 还是 AUTO ANALYZE,都会被忽略;

      • 对于分区表而言,不支持增量式分区统计信息合并的列类型,也不会被ANALYZE。不支持的类型除了上述类型之外,还包括:BOOLARRAY,INT4ARRAY,TEXTARRAY,BPCHARARRAY,VARCHARARRAY,INT8ARRAY,FLOAT4ARRAY,FLOAT8ARRAY。

    • 被标记为删除的列ALTER TABLE ... DROP COLUMN 后保留的逻辑列(attisdropped = true)不会被 ANALYZE;

    • 按列属性显式禁用

      • 设置了列属性enable_analyze = false的列,不会被 ANALYZE 和 AUTO ANALYZE;

      • 设置了列属性enable_auto_analyze = false的列,不会被 AUTO ANALYZE。

      • 关于上述列属性,详见后续章节。

    • JSONB 列未开启统计

      • 若列类型为 JSONB,且未打开 enable_jsonb_stats,则该列不会收集 JSONB 统计信息;

      • 如需依赖 JSONB 列的统计(例如复杂 JSON 过滤条件),需要先在列属性中开启 enable_jsonb_stats

小结:即使执行了 ANALYZE table_name;,上述列也可能因为类型或列属性的限制而被跳过,当pg_stats 中看不到对应统计记录时,可优先从这些限制排查。

  • 数据湖表的ANALYZE限制

    • 不支持对具体Timestamp、Version、Branch、SnapshotTag单独ANALYZE

典型用法

  • 典型推荐用法

    • 对 Join 列、Group By 列、过滤条件列执行列级 ANALYZE:

ANALYZE tablename (order_id, user_id, dt);
    • 导入或批量更新后,对受影响较大的表执行:

ANALYZE tablename;
    • 对外部表(FOREIGN TABLE / IMPORT FOREIGN SCHEMA / EXTERNAL DATABASE 下的表)在首次查询前执行:

ANALYZE foreign_table;
  • 通过设置列属性,跳过特定列的统计收集

    • Hologres 支持通过列级属性控制是否对某列执行 ANALYZE 或 AUTO ANALYZE,适用于以下场景:

      • 超宽列(如超长 Text 等)统计开销大,收集它的统计信息对查询计划帮助有限,甚至完全无用;

      • 某些列从不参与 Join、过滤或聚合,无需收集统计信息;

      • 需要减少 ANALYZE 或 AUTO ANALYZE 的资源消耗。

    • 控制参数为以下column options:

      • enable_analyze:控制该列是否参与手动 ANALYZE 和自动 AUTO ANALYZE,默认为 true

      • enable_auto_analyze:仅控制该列是否参与自动 AUTO ANALYZE,默认为 true

    • 设置方式(通过 ALTER TABLE 命令):

-- 禁用某列的 ANALYZE 和 AUTO ANALYZE
ALTER TABLE t ALTER COLUMN bitmap_col SET (enable_analyze = false);

-- 禁用某列的 AUTO ANALYZE,但仍允许手动 ANALYZE
ALTER TABLE t ALTER COLUMN large_text_col SET (enable_auto_analyze = false);

-- 恢复默认行为(重新启用)
ALTER TABLE t ALTER COLUMN bitmap_col RESET (enable_analyze);
ALTER TABLE t ALTER COLUMN large_text_col RESET (enable_auto_analyze);
    • 注意事项:

      • 设置 enable_analyze = false 后,该列在执行 ANALYZE table_name; 时会被自动跳过,但仍可通过手动 ANALYZE table_name(col); 显式收集;

      • 设置 enable_auto_analyze = false 后,该列不会被 AUTO ANALYZE 收集,但仍可通过手动 ANALYZE table_name(col); 显式收集;

      • 如果某列对查询计划有重要影响(如 Join 列、过滤条件列),不建议禁用其统计收集。

分区表与增量式分区 ANALYZE

为了降低对大分区表执行 ANALYZE 的开销,Hologres 支持增量式分区 ANALYZE:

  • 目标

    • 不再每次对分区父表进行全量采样;

    • 通过对子分区 ANALYZE + 合并统计信息的方式更新父表统计信息;

    • 对未发生变化的分区子表不再重复统计。

场景与限制

  • Hologres V2.0版本及以上,默认开启增量式分区ANALYZE,无需手动开启。具体请以产品版本说明为准;

  • 启用后,对某个分区子表执行 ANALYZE 时,会尝试联合其他子表的统计信息,合并出父表统计信息;

  • 能合并出父表统计信息的必要条件是:除当前 ANALYZE 的子表以外,该父表下所有其他子表均已有统计信息(包括行数统计信息,和列统计信息);

  • 因此,您可以:

    • 初次上线时,先对父表执行一次 ANALYZE,会自动检测需要ANALYZE的子表并逐个ANALYZE,最终合并出分区父表统计信息;

    • 后续新增分区时,只需对新增的子表执行 ANALYZE 即可。

简要示例

BEGIN;
DROP TABLE IF EXISTS t_parent;
CREATE TABLE t_parent(a int, b int) PARTITION BY LIST (a);
CREATE TABLE child1 PARTITION OF t_parent FOR VALUES IN (1);
CREATE TABLE child2 PARTITION OF t_parent FOR VALUES IN (2);
COMMIT;
insert into child1 values (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 2);
insert into child2 values (2, 1), (2, 2), (2, 3), (2, 4), (2, 5), (2, 5), (2, 5), (2, 5), (2, 5), (2, 5);

-- child2缺乏统计信息,无法合并出父表统计信息
dbname=# ANALYZE child1;
INFO:  auto merging of leaf partition stats to calculate root partition stats is not possible because partition child2 is not analyzed
ANALYZE

-- child1已具备统计信息,ANALYZE child2后,即可自动合并出父表统计信息
dbname=# ANALYZE child2;
ANALYZE

dbname=# SELECT tablename,
       attname,
       null_frac         AS "NF",
       avg_width,
       n_distinct,
       most_common_vals  AS "MCV",
       most_common_freqs AS "MCV_FRAQ"
FROM   pg_stats
WHERE  tablename = 't_parent';

 tablename | attname | NF | avg_width | n_distinct |  MCV  |  MCV_FRAQ
-----------+---------+----+-----------+------------+-------+------------
 t_parent  | a       |  0 |         4 |          2 | {1,2} | {0.5,0.5}
 t_parent  | b       |  0 |         4 |       -0.2 | {1,5} | {0.45,0.3}
(2 rows)

-- 此后新增分区,ANALYZE子表,仅需要对子表采样,即可自动合并出父表统计信息。

ANALYZE 分区父表

有时分区表的多个子表都发生了数据变化,不想逐个 ANALYZE 子表,那么可以针对父表做一次 ANALYZE。

当增量式分区 ANALYZE 被启用的情况下,手动执行分区父表的 ANALYZE 时,系统会自适应地筛选需要更新统计信息的子表,而非盲目地对所有子表进行一遍 ANALYZE。这一机制可显著降低大分区表的 ANALYZE 开销,同时确保统计信息的准确性。

行为说明

执行 ANALYZE partition_parent_table; 时,系统会自动识别以下两类子表,并优先对其进行ANALYZE统计收集,再统一合并出父表的统计信息:

  1. 统计信息变化的子表(stats-changed partitions)

    • 子表数据自上次 ANALYZE 以来发生了显著变化(插入、更新、删除);

    • 判断依据:

      • 数据变更行数达到变更阈值(1% * 上次的表行数)。

  2. 无法合并统计信息的子表(unable-to-merge partitions)

    • 子表缺失完整的统计信息,导致无法参与父表统计信息合并;

    • 常见原因包括:

      • 从未执行过 ANALYZE:子表统计信息完全缺失;

      • 列统计信息缺失:指定列缺少必要的统计信息(如 MCV、Histogram、NDVHLL Counter);

      • 统计信息与列类型不匹配:子表列类型发生变更,导致已有统计信息与当前列类型不一致;

      • 统计信息版本过旧:父表的统计信息版本(statistic_version)低于最新子表的统计信息版本,说明父表统计信息不是最新,需要重新合并。

执行示例与输出

-- 对分区父表执行 ANALYZE
ANALYZE partition_parent_table;

典型输出提示:

INFO:  will analyze 5 part tables first (stats changed 3, unable-to-merge 2)

此输出表示:

  • 系统识别出 5 个子表需要优先统计;

  • 其中 3 个子表因数据变更较多,需要触发统计信息更新;

  • 其中 2 个子表因缺失或不可用的统计信息被标记为无法合并,需要内部先触发一次 ANALYZE。

注意事项

  • 不建议对分区子表设置 autovacuum_enabled = false(表级别关闭 AUTO ANALYZE),否则可能导致该子表长期处于「无法合并」状态,除非再次手动 ANALYZE 该子表。

通过这一机制,Hologres 能够在保障统计信息质量的前提下,显著提升大分区表 ANALYZE 的执行效率,为查询优化器提供更及时、准确的决策依据。

逻辑分区表的ANALYZE

逻辑分区表(Logical Partitioned Table)是 Hologres 特有的分区表类型,与标准的 PostgreSQL 分区表(通过 PARTITION BY 创建物理子表)不同,逻辑分区表在物理上仍为单张表,仅在逻辑层面通过分区列值进行分区划分,提供了更灵活的分区管理能力。

逻辑分区表的ANALYZE逻辑,和物理分区表基本一致。唯一的区别是,逻辑分区表的子分区,不是一个单独的表,但它们和物理分区子表一样,仍然都有自己单独的行数统计信息和列统计信息等。

行为说明

对逻辑分区表执行 ANALYZE 时,系统采用与物理分区表类似但独立的处理逻辑:

  1. 自动发现逻辑分区

    • 对逻辑分区(父)表执行 ANALYZE logical_partitioned_table; 时,系统会自动从存储引擎查询该表的所有逻辑分区;

  2. 自适应筛选需要统计的逻辑分区

    • 与物理分区表类似,系统会识别以下逻辑分区并优先对其进行统计:

    • 统计信息变化的子表(stats-changed partitions)

      • 子表数据自上次 ANALYZE 以来发生了显著变化(插入、更新、删除),判断依据同前述物理分区表;

      • 缺失统计信息的逻辑分区:从未执行过 ANALYZE,或指定列缺少必要统计信息(如 HLL 计数器);

      • 统计信息不可用的逻辑分区:列统计信息与当前列类型不匹配,或统计信息过时。

    • 跳过空分区:行数为 0 的逻辑分区会被自动忽略。

    • 系统输出提示信息,例如:

    INFO:  will analyze 10 logical partitions first
  3. 逐分区采样与统计收集

    • 对每个需要统计的逻辑分区,系统构造带有分区列过滤条件的采样查询(如 WHERE user_id = 1 AND event_date = '2024-11-04');

    • 在该逻辑分区范围内进行数据采样,收集列级统计信息(NDV、MCV、Histogram、HLL 计数器等);

    • 统计信息以逻辑分区为粒度存储在 hologres_statistic.hg_table_statistic 中,通过 unique_name 字段区分不同逻辑分区。

  4. 合并父表统计信息

    • 当所有逻辑分区的统计信息收集完成后,系统自动触发统计信息合并,生成父表统计信息。

执行示例与输出

示例 1:对逻辑分区父表执行 ANALYZE

-- 创建逻辑分区表
CREATE TABLE user_events (
    user_id INT NOT NULL,
    event_type TEXT NOT NULL,
    event_date DATE NOT NULL,
    event_data INT
)
LOGICAL PARTITION BY LIST(user_id, event_date);

-- 插入不同逻辑分区的数据
INSERT INTO user_events SELECT 1, 'login', '2024-11-01', i FROM generate_series(1, 1000) i;
INSERT INTO user_events SELECT 1, 'logout', '2024-11-02', i FROM generate_series(1, 1000) i;
INSERT INTO user_events SELECT 2, 'purchase', '2024-11-03', i FROM generate_series(1, 1000) i;
INSERT INTO user_events SELECT 3, 'view', '2024-11-04', i FROM generate_series(1, 1000) i;

-- 对父表执行 ANALYZE
ANALYZE VERBOSE user_events;

典型输出:

INFO:  will analyze 4 logical partitions first
INFO:  analyzing hologres table "public.user_events" PARTITION (user_id=1,event_date='2024-11-01')
INFO:  analyzing hologres table "public.user_events" PARTITION (user_id=1,event_date='2024-11-02')
INFO:  analyzing hologres table "public.user_events" PARTITION (user_id=2,event_date='2024-11-03')
INFO:  analyzing hologres table "public.user_events" PARTITION (user_id=3,event_date='2024-11-04')
INFO:  try to merge root partition
INFO:  automatically merging leaf partition stats to calculate root partition stats

说明:

  • 系统自动发现了 4 个逻辑分区需要更新统计信息;

  • 逐个对每个逻辑分区进行统计收集;

  • 最后自动合并生成父表的全局统计信息。

示例 2:对指定逻辑分区执行 ANALYZE

-- 对单个逻辑分区执行 ANALYZE
ANALYZE user_events PARTITION (user_id=1, event_date='2024-11-01');

-- 对多个逻辑分区执行 ANALYZE
ANALYZE user_events
    PARTITION (user_id=1, event_date='2024-11-01')
    PARTITION (user_id=2, event_date='2024-11-03');

-- 对指定逻辑分区的特定列执行 ANALYZE
ANALYZE user_events
    PARTITION (user_id=1, event_date='2024-11-01') (user_id, event_type);

说明:

  • 可以使用 PARTITION 子句指定要统计的逻辑分区;

  • 支持同时指定多个逻辑分区;

  • 与标准 ANALYZE 一样,可以进一步指定要统计的列。

统计信息存储

逻辑分区表的统计信息存储在 hologres_statistic.hg_table_statistic 表中:

SELECT
    unique_name,
    schema_name,
    table_name,
    total_rows,
    sample_rows,
    nattr
FROM hologres_statistic.hg_table_statistic
WHERE table_name = 'user_events'
ORDER BY unique_name;

结果示例:

| unique_name | schema_name | table_name | total_rows | sample_rows | nattr |
|-------------|-------------|------------|------------|-------------| ----- |
| user_events | public | user_events | 4000 | 0 | 4 |
| user_events.a1b2c3d4e5f6... | public | user_events | 1000 | 1000 | 4 |
| user_events.f6e5d4c3b2a1... | public | user_events | 1000 | 1000 | 4 |
| user_events.1234567890ab... | public | user_events | 1000 | 1000 | 4 |
| user_events.abcdef123456... | public | user_events | 1000 | 1000 | 4 |

字段说明:

  • 父表记录

    • total_rows = 4000:所有逻辑分区的总行数;

    • sample_rows = 0:父表统计信息通过合并得出,未直接采样。

  • 逻辑分区记录unique_name 包含统计信息对象(表/分区)标识的 MD5 哈希):

    • 每个逻辑分区有独立的统计信息记录;

    • sample_rows = 1000:该逻辑分区实际采样的行数。

逻辑分区表 ANALYZE 最佳实践

  1. 优先对逻辑分区父表执行 ANALYZE

    • 对逻辑分区父表执行 ANALYZE 时,系统会自动发现并统计所有逻辑分区,无需手动指定每个分区;

    • 仅在需要快速更新特定逻辑分区统计时,才使用 PARTITION 子句指定分区。

  2. 利用增量统计信息更新

    • 当数据仅写入少数逻辑分区时,可以仅对这些分区执行 ANALYZE;

    • 系统会自动触发父表统计信息合并,无需重新统计所有分区。

  3. 注意逻辑分区数量

    • 当逻辑分区数量过多(如数千个)时,首次 ANALYZE 可能耗时较长,建议在业务低峰期执行;

  4. 配合 AUTO ANALYZE 使用

    • 逻辑分区表同样受 AUTO ANALYZE 管理,AUTO ANALYZE 会自动识别需要更新统计的逻辑分区。

ANALYZE 命令的可配置参数

参数

参数描述

支持版本

默认值

说明 / 使用示例

hg_experimental_analyze_foreign_partitions_access_limit

ANALYZE 外表时,随机采样操作最多允许访问的分区数量

v0.10及以上

0(不限)

-- 只采样100个分区,防止随机采样时扫描外表数据量超限制

ALTER DATABASE dbname SET hg_experimental_analyze_foreign_partitions_access_limit = 100;

hg_analyze_foreign_table_max_sample_row_count

ANALYZE 外表时,随机采样操作最大采样行数

v4.1及以上

0(不限),详见版本动态。

AUTO ANALYZE 自动统计信息收集

从 Hologres V0.10 起,Hologres支持自动统计信息收集机制 AUTO ANALYZE

  • 根据创建表、数据写入和变更情况自动判断哪些表需要统计信息更新;

  • 在后台异步调度统计信息收集任务,不需要用户手动逐表 ANALYZE;

  • 降低漏做 ANALYZE 导致缺失统计信息的风险。

开关与生效范围

数据库级开关

  • 配置参数为hg_enable_start_auto_analyze_worker,Hologres V0.10开始,即为默认打开。

-- 查看当前数据库是否开启 AUTO ANALYZE
SHOW hg_enable_start_auto_analyze_worker;

-- 关闭(仅临时排查、规避问题时使用)
ALTER DATABASE dbname SET hg_enable_start_auto_analyze_worker = OFF;

-- 重置回默认值ON(推荐)
ALTER DATABASE dbname RESET hg_enable_start_auto_analyze_worker;

说明:上述 GUC 为数据库级配置,SESSION级别/ROLE级别配置均无效,必须通过 ALTER DATABASE 设置,才能对该 DB 生效,仅 superuser 可修改。

表级开关

Hologres 支持对单张表单独控制 AUTO ANALYZE 行为。

行为说明

  • 关闭单表的 AUTO ANALYZE

ALTER TABLE my_table SET (autovacuum_enabled = false);
  • 开启单表的 AUTO ANALYZE(恢复默认行为)

-- 推荐,重置以恢复默认
ALTER TABLE my_table RESET (autovacuum_enabled);

-- 或者显式设置为 true(不推荐)
ALTER TABLE my_table SET (autovacuum_enabled = true);
  • 查看表的 autovacuum_enabled 状态

SELECT relname, reloptions FROM pg_class WHERE relname = 'my_table';

 relname  |         reloptions
----------+----------------------------
 my_table | {autovacuum_enabled=false}
(1 row)

典型使用场景

  1. 特殊业务表不需要统计信息

    • 某些表仅用于临时存储或日志记录,不参与复杂查询,无需收集统计信息;

    • 数据量大且经常变化,又无需统计信息的表,通过设置 autovacuum_enabled = false 可避免不必要的资源消耗。

  2. 统计信息已通过手动维护

    • 对于某些关键表,您可能已经建立了定期手动 ANALYZE 的流程,满足了业务需求。

  3. 临时禁用以降低资源占用

    • 在业务高峰期或紧急故障处理时,可临时关闭部分表的 AUTO ANALYZE;

    • 待业务恢复后再重新开启或手动执行 ANALYZE。

注意事项

  • 对于分区表:

    • 不建议对分区子表设置 autovacuum_enabled = false,否则可能导致该子表长期处于「无法合并」状态,影响父表统计信息的准确性;

    • 如需禁用,建议仅对分区父表设置。

  • 表级开关优先级高于数据库级开关:

    • 即使数据库级 AUTO ANALYZE 开启,设置了 autovacuum_enabled = false 的表仍不会被 AUTO ANALYZE 处理。

列级开关

Hologres 支持通过列级属性控制是否对某列执行 ANALYZE 或 AUTO ANALYZE,适用于以下场景:

  • 超宽列(如超长 Text 等)统计开销大,但对查询计划帮助有限;

  • 某些列从不参与 Join、过滤或聚合,无需收集统计信息;

  • 需要减少 AUTO ANALYZE 的资源消耗。

控制参数为以下column option:

  • enable_auto_analyze:仅控制该列是否参与自动 AUTO ANALYZE,默认为 true

  • 设置方式(通过 ALTER TABLE 命令):

-- 禁用某列的 AUTO ANALYZE,但仍允许手动 ANALYZE
ALTER TABLE t ALTER COLUMN large_text_col SET (enable_auto_analyze = false);

-- 恢复默认行为(重新启用)
ALTER TABLE t ALTER COLUMN large_text_col RESET (enable_auto_analyze);
  • 注意事项:

    • 列级别设置 enable_auto_analyze = false 后,AUTO ANALYZE 任务不会再收集该列的统计信息,但仍可通过手动 ANALYZE table_name;ANALYZE table_name(col); 显式收集;

    • 如果某列对查询计划有重要影响(如 Join 列、过滤条件列),不建议禁用其统计信息收集。

AUTO ANALYZE 的触发逻辑

AUTO ANALYZE 综合多类信号,判断是否需要对某个表执行统计信息更新:

  1. 数据变更量

    • 仅针对Hologres普通表(不包括外表);

    • 1分钟为周期,收集FE自身观察到的表INSERT/UPDATE/DELETE操作的行数,如果变化超过阈值,则触发一次 AUTO ANALYZE(快速响应);

    • 10分钟为周期,从存储引擎获取各表的插入/更新/删除等变化行数,超过阈值,则触发一次 AUTO ANALYZE(精确校准);

  2. Schema 变更

    • 仅针对Hologres普通表(不包括外表);

    • 1分钟为周期,收集发生如下变化的表,进行 AUTO ANALYZE:

      • ADD / DROP COLUMN;

      • 分区表(包括逻辑分区表)ATTACH / DETACH 子分区。

  3. 缺失统计信息 / 无法合并分区父表统计信息

    • 适用于Hologres普通表和外表;

    • 1分钟为周期,收集缺失统计信息的表/字段,以及无法达到统计信息增量合并条件的子分区。

  4. 外表

    • 仅适用于非 External Database 下,通过CREATE FOREIGN TABLEIMPORT FOREIGN SCHEMA引入或 Auto Load 机制自动引入的外表;

    • 当前仅支持对 MaxCompute 外表进行 AUTO ANALYZE;

    • 4小时为周期,定期检查DB中所有外表,在两次检查之间,有无外部数据变更(有外部数据变更的标准是对应外表的 last_modify_timestamp 处于两次检查间隔之间),有则触发一次 AUTO ANALYZE。

  5. 保底统计

    • 在凌晨 1:00-5:00 的窗口内,会对持续有变更但未触发阈值(>5000行变化,<10%变化量)的表做一次「兜底」AUTO ANALYZE,捕捉字段数据分布的漂移(例如,第二天0点后写入的date类型字段,和前一天完全不同,数据分布发生变化)。

  6. 访问热点表(仅用于External Database)

    • External Database 打开enable_auto_analyze参数之后,Hologres系统将开始统计系统本次启动以来,近期访问过的表,将他们加入观测列表;

    • 1小时为周期,将观测列表中「近期频繁访问」的表,触发一次 AUTO ANALYZE;

    • 要注意的是,系统重新启动之后,访问过的表将清除,并重新开始记录。

External Database 的 AUTO ANALYZE

  • HologresV3.0版本开始支持外部数据库(External Database)功能,创建 External Database 时,可以开启 AUTO ANALYZE(默认为关闭,详见版本动态):

-- 创建 External Database 时,开启 AUTO ANALYZE
-- 参考文档:https://help.aliyun.com/zh/hologres/developer-reference/create-external-database
CREATE EXTERNAL DATABASE <ext_database_name> WITH
  metastore_type 'maxcompute'
  mc_project 'project_name'
  enable_auto_analyze 'true';

-- 创建 External Database 之后,为其开启 AUTO ANALYZE
ALTER EXTERNAL DATABASE dbname WITH enable_auto_analyze 'true';

功能限制:V3.2及以下,External Database 能支持AUTO ANALYZE的条件是,CREATE EXTERNAL DATABASE上配有Access KeyAccess Secret。不支持对SLRSTS形式配置的External DatabaseAUTO ANALYZE。V4.0及以上无限制。

  • External Database 上的 AUTO ANALYZE 支持的metastore_type范围为:dlf,dlf-paimon,dlf-rest,maxcompute

  • External Database 上的 AUTO ANALYZE 支持的表格式包括:MaxCompute、Paimon、Iceberg

  • External Database 上的 AUTO ANALYZE,默认会采用 External Database 的 Owner 身份,采用Time-based One-Time Password (TOTP)的认证方式来执行ANALYZE任务。如果Owner无充足的表权限,则系统无法成功执行 AUTO ANALYZE 任务。

  • External Database 中的一张外表,能被 AUTO ANALYZE,需要满足:

    • External Database的数据库配置hg_enable_start_auto_analyze_worker = on; (默认on)

    • External Database的属性enable_auto_analyzetrue(默认不配置,为false,详见版本动态)

    • External Database Owner 需要有数据湖Project(如有)和表的查询权限

    • 表在3天内被至少访问过一次

      • External Database 下的 AUTO ANALYZE,只关注被访问过至少一次的外表;

      • 系统重新启动后,如果外表被访问过至少一次,则 AUTO ANALYZE 系统会将其加入观测列表,定期触发这些表的 AUTO ANALYZE;

注:External Database 中未访问过的外表,第一次访问,会通过快速行数估算机制,获取行数作为保底统计信息(见下文"快速行数估算"章节),仍有一定的统计信息保障。

AUTO ANALYZE 的资源限制

为了避免系统后台的 AUTO ANALYZE 任务,给用户前台任务造成影响,Hologres 为 AUTO ANALYZE 功能制定了如下资源限制:

  • AUTO ANALYZE 任务执行时,默认单worker限制的内存是4 GB,如表数据量过大,采样可能超出内存而导致 AUTO ANALYZE 的采样SQL失败,从而仅能收集行数信息,无法收集列分布信息(MCV、Histogram、NDV等)。可调整auto_analyze_work_memory_mb改变其行为。实例规格越大,AUTO ANALYZE 可用内存限制越大。

  • 实例级别 AUTO ANALYZE 任务同时调度的并发,通常情况下不会超过4,极端情况下不超过6。

  • 同一个分区表下的子分区 AUTO ANALYZE 任务,同时调度的并发最多为3。

  • AUTO ANALYZE默认最大收集256的统计信息,如表超过256列,取前256列(对于分区表,分区列是优先列,即使在256列之后,也会被收集)。可通过调整hg_experimental_auto_analyze_max_columns_count改变此值。

  • AUTO ANALYZE 任务的采样子SQL,采用低优先级的Background Pool来运行,并限制了Query执行层并发,这会导致 AUTO ANALYZE 任务执行时间相比手动 ANALYZE 更长,用户无需重视。

  • AUTO ANALYZE 对于外表,只会收集分区列的列统计信息(例如,MCV等),不会对分区列以外的列,进行采样收集列统计信息。

AUTO ANALYZE 的可配置参数

Hologres AUTO ANALYZE 功能默认情况下无需修改任何参数。

在极少数业务场景下(例如数据写入更新不频繁场景、查询负载不需要统计信息、系统出现了 AUTO ANALYZE 引发的负载升高等问题),用户可以通过修改部分默认参数来调整AUTO ANALYZE的行为,实现行为干预,或达到部分性能调优的目的。

说明:只有superuser能调整 AUTO ANALYZE 的默认行为,且都需要DB级别设置参数,且在下一分钟后生效。

-- Superuser,DB级别修改 AUTO ANALYZE 参数的默认值
ALTER DATABASE dbname SET <GUC> = <values>;

参数

参数描述

支持版本

默认值

说明 / 使用示例

hg_enable_start_auto_analyze_worker

开启 AUTO ANALYZE 功能

v0.10及以上

on

-- 临时关闭DBAUTO ANALYZE功能ALTER DATABASE dbname SET hg_enable_start_auto_analyze_worker = off;

hg_experimental_auto_analyze_max_columns_count

AUTO ANALYZE 自动收集统计信息的列数

v1.1.0及以上

256

ALTER DATABASE dbname SET hg_experimental_auto_analyze_max_columns_count =300;

auto_analyze_work_memory_mb

AUTO ANALYZE 单个表的内存限制,单位是MB

v1.1.54及以上

4096

-- 修改为9GBALTER DATABASE dbname SET auto_analyze_work_memory_mb = 9216;默认单个worker 4 GB,实例规格越大,Worker越多,真实内存限制越大)

auto_analyze_work_statement_timeout

AUTO ANALYZE 任务执行的超时时间,单位是ms

V2.0及以上

3600000

-- 修改为3hALTER DATABASE dbname SET auto_analyze_work_statement_timeout = '3h';

hg_experimental_auto_analyze_max_foreign_table_partitions

AUTO ANALYZE 过程中,最多访问的外表分区个数

v1.1.54及以上

100

如果外表分区数超过100,默认采用一级分区值字典序最大的100个分区的行数,来预估外表总体行数和分区列MCV。

hg_auto_analyze_run_with_serverless_computing

AUTO ANALYZE 是否采用 Serverless 资源运行

v3.1及以上

off(Serverless型实例默认为on)

一般无需调整,AUTO ANALYZE 通常消耗资源不多,且利用低优先级进程后台运行,对实例负载影响小。

hg_auto_analyze_serverless_computing_query_priority

Serverless 任务优先级,范围 1~5,数值越大优先级越高。注:需要先开启hg_auto_analyze_run_with_serverless_computing

v3.1及以上

2

-- 修改为最高优先级ALTER DATABASE dbname SET hg_auto_analyze_serverless_computing_query_priority = 5;

快速行数估算(Fast Num of Rows)

Hologres V3.1开始,Hologres 新增快速行数估算功能。当发现执行查询的SQL中有表缺乏统计信息,或者统计信息可能过期时,Hologres 可以通过底层存储或外部系统的元信息快速估算表行数,从而生成更合理的执行计划。

Hologres V3.2开始,快速行数估算(Fast Num of Rows)功能默认打开。

开关

开启快速行数估算的方式:

-- 关闭(仅适用于临时处置,或全库明确不需要统计信息的情况)
ALTER DATABASE dbname SET hg_experimental_get_fast_num_of_rows = OFF;

-- V3.2及以上,打开(重置回默认值)
ALTER DATABASE dbname RESET hg_experimental_get_fast_num_of_rows;

-- V3.1及以下,打开
ALTER DATABASE dbname SET hg_experimental_get_fast_num_of_rows = ON;

注意:快速行数估算不能替代完整的统计信息收集,仍然建议在关键业务表上通过 ANALYZE/AUTO ANALYZE 保持统计信息新鲜。

使用限制

  • 快速行数估算适用于普通表(包括分区表)、External Database中的外表等情况。

  • 快速行数估算功能,估算出的行数不保证完全准确。例如,为性能起见,在Hologres分区表上,最多只会使用60个分区(默认)的行数统计去估算分区表总体行数。

  • V4.1.15及以下,快速行数估算对外表类型(Foreign Table)默认不开启,可通过参数hg_experimental_enable_foreign_table_get_fast_num_of_rows开启。V4.1.16及以上默认开启。

  • 对于外表类型,快速行数估算获取仅支持MaxCompute外表,Paimon外表和Iceberg外表。

示例

  1. hg_experimental_get_fast_num_of_rows示例

若表没有统计信息,开启快速行数估算后,可得到更准确的行数。(Hologres V3.2及以上默认开启)

-- V3.2+
create table test_tbl (a int);
insert into test_tbl select * from generate_series (1, 999);

-- 准确的行数估计(rows=999)
explain select count(1) from test_tbl ;
                                       QUERY PLAN
----------------------------------------------------------------------------------------
 Final Aggregate  (cost=0.00..5.00 rows=1 width=8)
   ->  Gather  (cost=0.00..5.00 rows=10 width=8)
         ->  Partial Aggregate  (cost=0.00..5.00 rows=10 width=8)
               ->  Local Gather  (cost=0.00..5.00 rows=20 width=8)
                     ->  Partial Aggregate  (cost=0.00..5.00 rows=20 width=8)
                           ->  Seq Scan on test_tbl  (cost=0.00..5.00 rows=999 width=1)

下面是一个线上的真实案例:

未开启此功能时,若表没有统计信息,查询计划中Scan节点会有rows=1000行(表示没有统计信息,根据默认1000行预估生成计划)

image

当开启该功能后,若表没有统计信息,查询计划Scan节点rows不等于1000行(系统调用了底层存储引擎的元信息,获取了表的行数)。

image

快速行数估算的可配置参数

参数

参数描述

支持版本

默认值

说明 / 使用示例

hg_experimental_get_fast_num_of_rows

是否开启快速行数算。

v3.1及以上

off(V3.1)on(V3.2+)

hg_experimental_enable_foreign_table_get_fast_num_of_rows

是否打开外表行数估算。

v3.1及以上

off(V4.1.15及以下)on(V4.1.16+)

-- 开启方式ALTER DATABASE dbname SET hg_experimental_enable_foreign_table_get_fast_num_of_rows = on;

hg_experimental_fast_num_rows_foreign_partitions_access_limit

对于外表分区表,最多获取多少个分区的行数,作为整体估算的依据。注:需打开外表行数估算才生效。

v3.1及以上

60

这是为了控制快速行数估算的时间开销。

hg_get_fast_num_of_rows_holo_partitions_access_limit

对于Hologres物理分区表,最多获取多少个分区的行数,作为整体估算的依据。

v3.1及以上

60

这是为了控制快速行数估算的时间开销。

查看 ANALYZE 与 AUTO ANALYZE 的历史执行记录

ANALYZE 与 AUTO ANALYZE 在执行之后,其执行记录会被写入 Query Log,用户可以通过 hologres.hg_query_log 视图查看 ANALYZE 与 AUTO ANALYZE 的历史执行情况,包括执行的 SQL、耗时、状态等信息。

如何识别 ANALYZE 与 AUTO ANALYZE 的 Query Log 记录

ANALYZE 和 AUTO ANALYZE ,及其发出的采样SQL,会被单独记录在 Query Log 中。

执行记录在 Query Log 中具有以下特征:

字段

ANALYZE

AUTO ANALYZE

说明

usename

执行ANALYZE的用户名

system

AUTO ANALYZE 使用系统内部账户执行,在 Query Log 中统一显示为 system

application_name

执行ANALYZEsessionapplication name

AutoAnalyze

AUTO ANALYZE 框架连接使用 AutoAnalyze作为application_name

采样子 SQL 的 application_name

Hologres SQL Generated BY ANALYZE

Hologres SQL Generated BY AUTO ANALYZE

command_tag

ANALYZE

ANALYZE

所执行的命令类型

采样子 SQL 的 command_tag

SELECT

SELECT

采样子SQLSELECT语句,可通过此语句查看采样的资源消耗。

ANALYZE 及其发出的采样SQL,通过query字段的注释,或者extended_info->>'source_query_id'关联。

SELECT query_id,
       extended_info->>'src_query_id' as "source query id",
       application_name,
       status,
       duration
FROM   hologres.hg_query_log
WHERE  query_start >= now() - interval '1 hour'
  AND  application_name IN ('AutoAnalyze', 'Hologres SQL Generated BY AUTO ANALYZE')
ORDER BY query_start DESC
LIMIT  2;
      query_id       |   source query id   |            application_name            | status  | duration
---------------------+---------------------+----------------------------------------+---------+----------
 1004019226350863009 | 1004019226350778807 | Hologres SQL Generated BY AUTO ANALYZE | SUCCESS |      119
 1004019226350778807 |                     | AutoAnalyze                            | SUCCESS |     3276

查询示例

  • 查看最近的 AUTO ANALYZE 执行记录

SELECT usename,
       status,
       duration,
       query_start,
       query_end,
       query,
       application_name
FROM   hologres.hg_query_log
WHERE  query_start >= now() - interval '1 hour'
  AND  application_name IN ('AutoAnalyze')
ORDER BY query_start DESC
LIMIT  20;

       query_id,
       extended_info->>'src_query_id' as "source query id"
  • 查看某张表的 AUTO ANALYZE 执行历史

SELECT status,
       duration,
       query_start,
       query
FROM   hologres.hg_query_log
WHERE  query_start >= now() - interval '1 day'
  AND  application_name IN ('AutoAnalyze')
  AND  query LIKE '%my_table_name%'
ORDER BY query_start DESC;
  • 统计近3天 AUTO ANALYZE 的执行概况

SELECT query_date,
       status,
       COUNT(*)          AS task_count,
       AVG(duration)     AS avg_duration_ms,
       MAX(duration)     AS max_duration_ms
FROM   hologres.hg_query_log
WHERE  query_start >= CURRENT_DATE::timestamptz - interval '2 day'
  AND  application_name IN ('AutoAnalyze')
  AND  command_tag = 'ANALYZE'
  AND  (status = 'SUCCESS' OR (
            message NOT LIKE '%does not exist%'
        AND message NOT LIKE '%retry later%'))
GROUP BY query_date, status
ORDER BY query_date DESC;
  • 查看近1天失败的 AUTO ANALYZE 任务

SELECT query_start,
       duration,
       message,
       query
FROM   hologres.hg_query_log
WHERE  query_start >= now() - interval '1 day'
  AND  application_name IN ('AutoAnalyze', 'Hologres SQL Generated BY AUTO ANALYZE')
  AND  status != 'SUCCESS'
  AND  (message NOT LIKE '%does not exist%'
        AND message NOT LIKE '%retry later%')
ORDER BY query_start DESC;

注意事项

  • 由于 AUTO ANALYZE 连接以内部管理员身份发起,普通用户需具备 pg_read_all_stats 角色或数据库管理员权限才能查看完整的 AUTO ANALYZE 执行记录;

  • 若发现 Query Log 中长时间没有 AUTO ANALYZE 记录,建议检查 AUTO ANALYZE 开关是否已开启。

查看与排查统计信息

查看表的统计信息(hologres_statistic.hg_table_statistic)

表的统计信息被存储在hologres_statistic.hg_table_statistic表中,同时在系统表中可以观测到。

  1. 查询该表获取最近一次analyze的统计信息。

SELECT schema_name,                -- 表的schema
       table_name,                 -- 表名
       user_name,                  -- 最近一次ANALYZE的用户
       schema_version,             -- 最近一次ANALYZE的表Schema版本
       total_rows,                 -- 最近一次ANALYZE的行数
       sample_rows,                -- 最近一次ANALYZE获取统计信息的采样行数
       analyze_timestamp,          -- 最近一次ANALYZE的结束时间
       analyze_count               -- 到当前为止总计的ANALYZE次数
FROM   hologres_statistic.hg_table_statistic
WHERE  unique_name = hologres.hg_internal_statistic_unique_name ('schemaname', 'tablename')
ORDER BY analyze_timestamp DESC;

-- 示例输出
 schema_name | table_name |    user_name     | schema_version | total_rows | sample_rows |  analyze_timestamp  | analyze_count
-------------+------------+------------------+----------------+------------+-------------+---------------------+---------------
 public      | test_fnr   |   BASIC$test_fnr |             -1 |        999 |         999 | 2026-03-02 22:05:29 |             2
(1 row)

V3.1以下,

  • 每个表在hologres_statistic.hg_table_statistic表中有0~n条记录。0条表示从未进行过ANALYZE,1条及以上表示运行过analyze。

  • 若出现两条及以上的情况,两条记录的schema_version一定不一样,因为表的schema变化了(例如,ADD COLUMN,CALL SET_TABLE_PROPERTY等)会产生新的版本,会增加一条统计信息记录,老的schema_version对应的记录不再被使用。

  • 示例查询结果如下,同一个表有2条记录,而第二条记录的schema_version低于第一条,那么第二条将作废,不会被使用,也无需关注。Hologres暂不会清理hg_table_statistic表中的历史过期记录,同时用户无需关心老的数据。

 schema_name | table_name |    user_name     | schema_version | total_rows | sample_rows |  analyze_timestamp  | analyze_count
-------------+------------+------------------+----------------+------------+-------------+---------------------+---------------
 public      | test_fnr   |   BASIC$test_fnr |             13 |        999 |         999 | 2026-03-01 18:05:29 |             2
 public      | test_fnr   |   BASIC$test_fnr |             12 |        999 |         999 | 2026-03-01 08:05:29 |             1
(1 row)

V3.1及以上,

  • 每个表在hologres_statistic.hg_table_statistic表中有0~1条记录,0条表示从未进行过ANALYZE,1条表示运行过analyze。

  • schema_version统一为-1(代表Deprecated)。

  • 这意味着,很多DDL操作,都不再会使统计信息失效。例如CALL SET_TABLE_PROPERTY等,不会重新触发AUTO ANALYZE,继续沿用统计信息即可。相比Hologres V3.0及以前,大幅减少了AUTO ANALYZE的触发频率。

  1. 查询行数等统计信息

行数信息记录在pg_class表的reltuples字段。

-- relallvisible > 0:表有行数统计信息
-- relallvisible = 0:表行数未知,此时不能参考reltuples
-- relallvisible < 0:表无统计信息
SELECT relallvisible, reltuples FROM pg_class WHERE relname = 'test_table';

如果表没有统计信息,可参看下文"查看缺失统计信息的表"一节,找出缺失的原因。

  1. 查询列统计信息

通过查询pg_stats视图,可获取当前表的所有列的统计信息。例如,获取test_tableds列统计信息:

select * from pg_stats where tablename = 'test_table' and attname = 'ds';

 schemaname | tablename  | attname | inherited | null_frac | avg_width | n_distinct | most_common_vals | most_common_freqs | histogram_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram
------------+------------+---------+-----------+-----------+-----------+------------+------------------+-------------------+------------------+-------------+-------------------+------------------------+----------------------
 public     | test_table | ds      | f         |         0 |         4 |          1 | {20241104}       | {1}               |                  |             |                   |                        |
(1 row)

如果列没有统计信息,可参看下文"查看缺失统计信息的表"一节,找出缺失的原因。

查看缺失统计信息的表

Hologres 提供视图 HG_STATS_MISSING(视图名称以实际版本为准),用于查看当前 DB 中缺失统计信息的表,便于排查需要补充 ANALYZE 的对象。

具体字段与使用方式请参考对应实例文档或控制台帮助。

常见异常与排查建议

  1. 统计信息hologres_statistic.hg_table_statistic表中,查出0条的可能原因:

  • 从未执行过 ANALYZE(手动或 AUTO ANALYZE);

  • AUTO ANALYZE 未工作,或该表未满足触发条件;

建议操作:

  • 先手动执行:

ANALYZE schema_name.table_name;
  • 若仍长期无法由 AUTO ANALYZE 覆盖,建议检查 AUTO ANALYZE 开关、GUC 配置,或联系技术支持。

  1. analyze_timestamp 明显过旧可能原因:

  • AUTO ANALYZE 被关闭或限制(如 autovacuum_enabled = false);

  • AUTO ANALYZE 资源不足或失败(可结合日志/监控排查);

建议操作:

  • 手动 ANALYZE 一次后观察效果;

  • 检查:

    • hg_enable_start_auto_analyze_worker 是否开启;

    • 是否误设置了 autovacuum_enabled = false 或相关 GUC 限制过严;

    • 查看 Query Log 中是否有 AUTO ANALYZE 相关任务的报错。

  1. 查询计划中行数估计异常(明显偏小或偏大)

  • 检查对应表是否缺失统计或统计过旧;

  • 检查谓词列是否有统计信息(pg_stats),对关键列执行列级 ANALYZE;

  • 是否关闭或未启用快速行数估算功能。

  1. 分区表父子统计信息不一致或父表缺失统计信息

  • 现象:分区父表在 hologres_statistic.hg_table_statistic 中没有记录,或 total_rows 明显小于所有子表行数之和,或父表的分区列统计信息MCV分布落后(比如pg_statsds列缺少昨日的分布);

  • 排查要点:

    • 检查增量式分区 ANALYZE / AUTO ANALYZE是否被关闭;

SHOW hg_experimental_enable_incremental_analyze;
SHOW hg_experimental_enable_incremental_auto_analyze;
  • 使用 HG_STATS_MISSING视图查看是否存在无法合并的子表;

  • 查看 Query Log 中是否有 AUTO ANALYZE 相关任务的报错;

  • 对缺失统计信息的子表手动执行 ANALYZE child_table; 或在业务低峰期对父表执行一次 ANALYZE partition_parent_table;,让系统补齐并合并统计信息。

  1. 某些列在 pg_stats 中没有统计信息

  • 现象:表存在该列,但pg_stats视图中看不到对应列的统计信息。

  • 排查要点:

    • 检查是否通过列属性禁用了统计(enable_analyze = falseenable_auto_analyze = false);

SELECT attoptions
  FROM pg_attribute
 WHERE attrelid = 'tablename'::regclass::oid
   AND attname = 'columnname';
-[ RECORD 1 ]----------------------
attoptions | {enable_analyze=false}
  • 确认该列是否参与过 ANALYZE(手动或 AUTO ANALYZE),必要时执行列级 ANALYZE table_name(col_name);

SELECT query_id,
       application_name,
       status,
       query_start,
       query
FROM   hologres.hg_query_log
WHERE  query_start >= now() - interval '1 hour'
  AND  application_name IN ('Hologres SQL Generated BY ANALYZE', 'Hologres SQL Generated BY AUTO ANALYZE')
  AND  query like '%tablename%'
ORDER BY query_start DESC
LIMIT  2;
  • 是否为特殊列类型(byteajsonb)。

  • 如果表执行了AUTO ANALYZE,但是所有列都没有统计信息,则考虑是否AUTO ANALYZE任务执行异常。例如AUTO ANALYZE是否执行超时,因auto_analyze_work_statement_timeout默认为1h,如果hologres.hg_query_log 中的AUTO ANALYZE任务,执行了duration >= 3600000,这种情况下,只会采集行数信息,而不会有列统计信息。

  1. AUTO ANALYZE 已执行但查询计划未明显改善

  • 现象:从 hologres.hg_query_log 中能看到针对某表的 AUTO ANALYZE 记录,但实际查询计划仍然使用明显不合理的行数估计或 Join 顺序;

  • 排查要点:

    • AUTO ANALYZE是否执行超时,因auto_analyze_work_statement_timeout默认为1h,如果hologres.hg_query_log 中的AUTO ANALYZE任务,执行duration >= 3600s,这种情况下,只会采集行数信息,而不会有列统计信息。

    • 检查是否存在 Hint、固定 Join 顺序、遗留的会话级 GUC(如 enable_nestloop 等)干扰了优化器选择;

    • 对关键表/列执行一次手动 ANALYZE 后重跑查询,若仍无改善,建议结合 Query Log、FE 日志或上报技术支持进一步排查。

  1. 统计信息导致的 OOM / 内存超限问题

  • 现象:复杂多表 Join 报错 Query executor exceeded total memory limitation ...,或计划选择了极端不合理的 Join 策略(如大表驱动大表的 Nested Loop 等);

  • 排查要点:

    • 确认相关表是否缺失统计或统计严重过旧(结合hg_table_statistic中的记录和 AUTO ANALYZE 执行记录);

    • 对 Join 列、过滤列执行列级 ANALYZE,必要时提高采样精度或打开快速行数估算能力;

    • 若问题只在某些极端数据分布或峰值场景出现,可与技术支持评估是否需要调整统计模型或相关 GUC(如 AUTO ANALYZE 阈值、内存上限等)。

Serverless 运行 ANALYZE 与 AUTO ANALYZE

Hologres V3.1开始,在使用 Serverless 型实例或已开通 Serverless 计算资源的实例中,ANALYZE 和 AUTO ANALYZE 支持运行在 Serverless 资源上,减轻对本实例的 CPU / 内存压力。

本节结合相关 GUC,说明在 Serverless Computing 场景下,手动 ANALYZE 与 AUTO ANALYZE 的典型行为与推荐配置。

手动 ANALYZE 与 Serverless Computing

  • hg_serverless_computing_enable_analyze_statement

    • 描述:控制手动 ANALYZE 语句是否支持通过 Serverless 任务执行;

    • 行为:

      • on(默认)时,系统允许将 ANALYZE 语句下推到 Serverless 计算资源执行,统计任务对实例本身的影响更小;

      • off 时,ANALYZE 在本实例资源上执行。

    • 典型建议:

      • 在 Serverless 型实例中,默认为on,只允许利用 Serverless 资源完成统计任务;

      • 如需排查问题或对资源使用有特殊要求时,可临时设置为 off,让 ANALYZE 明确在本地资源上运行。

AUTO ANALYZE 与 Serverless Computing

系统会在生成 AUTO ANALYZE 任务时,根据以下 GUC 决定是否使用 Serverless 资源,以及如何控制 Serverless 任务行为:

  • hg_auto_analyze_run_with_serverless_computing

    • 描述:是否通过 Serverless 计算资源执行 AUTO ANALYZE 任务。普通实例默认off,Serverless型实例默认on

    • 行为:

      • on 时,AUTO ANALYZE 任务会将采样计算发送到 Serverless 资源池;

      • off 时,AUTO ANALYZE 继续通过本实例资源完成统计。

-- DB级别设置
ALTER DATABASE datname SET hg_auto_analyze_run_with_serverless_computing = on;
  • hg_auto_analyze_serverless_computing_query_priority

    • 描述:Serverless AUTO ANALYZE 任务的优先级,范围为 1~5,值越大优先级越高,默认 2

    • 行为:

      • 当开启 Serverless AUTO ANALYZE 时,系统会通过 SET hg_experimental_serverless_tasks_query_priority = <value>; 为每条统计任务设置对应优先级;

      • 适用于与其他 Serverless 任务(如 ETL、离线查询)共用资源池时,控制统计任务在整体队列中的抢占能力;

    • 建议:

      • 生产环境中通常保持在中等优先级(如默认 2 或适当调大到 3),避免与核心业务作业争抢过多资源;

      • 对统计信息及时性要求极高、且 Serverless 资源充足的场景,可适当提高优先级。

  • hg_auto_analyze_serverless_computing_enable_persisted_snapshot

    • 描述:是否在 Serverless AUTO ANALYZE 任务中采用持久化快照(persisted snapshot),即通过 SET hg_experimental_enable_persisted_snapshot = on/off; 控制是否跳过额外的 flush;

    • 非 Serverless 型实例默认off,Serverless 型实例默认on

    • 行为:

      • on 时,统计任务会尽量复用持久化快照,减少触发一次 flush,更适合高频统计或大量分区表场景;

      • off 时,统计任务尽量采用更新的snapshot,适合对一致性或特定版本隔离有更高要求的场景。

    • 建议:

      • 没有必要不作调整。

Serverless Computing 场景下的使用建议

  1. 优先利用 Serverless Computing 承载重型 ANALYZE 任务

    • 在 ANALYZE 数据量超大的表或外表时,建议开启:

      • 手动 ANALYZE:set hg_computing_resource = 'serverless'; ANALYZE my_table;

      • AUTO ANALYZE:ALTER DATABASE mydb SET hg_auto_analyze_run_with_serverless_computing = on;

    • 这样可以将统计计算压力迁移到 Serverless 资源池,降低对实例在线查询的干扰。

  2. 根据业务重要性设置 Serverless AUTO ANALYZE 任务优先级

    • 在 Serverless 型实例中,对统计时效敏感、依赖最新统计信息的关键业务库,可适当提高 hg_auto_analyze_serverless_computing_query_priority

    • 在普通实例中,通常仍使用本地资源做 AUTO ANALYZE 即可。

  3. 调参前同样遵循"小步试探"原则

    • Serverless Computing 相关 GUC 同样属于高级参数,调整前建议先在测试或预发环境验证:

      • 观察统计任务在 Serverless 资源池中的排队与执行时长;

      • 关注对核心业务查询的延迟与资源占用影响;

    • 确认无明显副作用后,再在生产环境分库或分阶段推广。