GUC参数

更新时间:
复制 MD 格式

为了更好地支持Hologres用户丰富的使用场景,Hologres提供一些GUC参数。本文将介绍HologresGUC参数的含义以及如何使用。

使用限制

GUC参数对系统表不生效。

GUC参数一览表

GUC名称

适用场景

说明

使用示例

hg_enable_start_auto_analyze_worker

开启Auto Analyze,以及Auto Analyze相关配置,详情请参见ANALYZEAUTO ANALYZE

HologresV1.1及以上版本默认开启,值为on

set hg_enable_start_auto_analyze_worker = on;

hg_auto_check_table_changes_interval

默认值为10min

set hg_auto_check_table_changes_interval = '10min';

hg_auto_check_foreign_table_changes_interval

默认值为4h

set hg_auto_check_foreign_table_changes_interval = '4h';

hg_auto_analyze_max_sample_row_count

默认值为16777216

set hg_auto_analyze_max_sample_row_count = 16777216;

hg_fixed_api_modify_max_delay_interval

默认值为3d

set hg_fixed_api_modify_max_delay_interval = '3day';

hg_foreign_table_max_partition_limit

MaxCompute外部表分区限制。如需调整限制可通过该GUC参数进行设置。

  • Hologres v3.0.7之前版本(不含),默认值为512,支持范围为0-1024

  • Hologres v3.0.7及以上版本,默认值为0,表示不作限制,支持范围为0-1024

set hg_foreign_table_max_partition_limit = 128;

hg_experimental_query_batch_size

MaxCompute性能调优参数,详情请参见优化MaxCompute外部表的查询性能

默认值为8192

set hg_experimental_query_batch_size = 4096;

hg_foreign_table_split_size

默认值为64,不建议设置过大。

set hg_foreign_table_split_size = 128;

hg_foreign_table_executor_max_dop

默认值调整为与实例Core数相同,最大为128

set hg_foreign_table_executor_max_dop = 32;

hg_foreign_table_executor_dml_max_dop

默认值为32

set hg_foreign_table_executor_dml_max_dop = 16;

hg_enable_access_odps_orc_via_holo

HologresV1.1及以上版本默认开启,值为on

set hg_enable_access_odps_orc_via_holo = on;

hg_experimental_enable_result_cache

查询结果缓存。

默认值为on,不建议关闭。

set hg_experimental_enable_result_cache = on;

optimizer_join_order

内部性能调优参数,详情请参见优化查询性能

默认值为exhaustive,后面可以接Query命令。

set optimizer_join_order = query;

optimizer_force_multistage_agg

默认值为off,按需开启。

set optimizer_force_multistage_agg = on;

hg_anon_enable

数据脱敏函数,详情请参见数据脱敏

默认值为off,建议数据库级别按需开启。

alter database <DB_NAME> set hg_anon_enable = on;

hg_experimental_encryption_options

数据加密规格设置,详情请参见数据存储加密

默认值为off,建议数据库级别按需开启。

alter database <DB_NAME> set hg_experimental_encryption_options='AES256,623c26ee-xxxx-xxxx-xxxx-91d323cc4855,AliyunHologresEncryptionDefaultRole,187xxxxxxxxxxxxx';

statement_timeout

活跃query超时时间,详情请参见管理Query

默认值为8h,建议根据业务情况,session级别设置不同粒度的超时时间。

set statement_timeout = 5000 ;

idle_in_transaction_session_timeout

空闲事务的超时时间,详情请参见管理Query

默认值为10min,建议数据库级别设置,否则当事务泄漏时容易造成死锁。

alter database db_name set idle_in_transaction_session_timeout=300000;

idle_session_timeout

自动释放空闲连接超时时间,详情请参见连接数管理

默认值为0,即不会自动释放。建议设置,否则连接数太多导致超过实例默认上限,从而无法连接。

alter database <DB_NAME> SET idle_session_timeout = 600000;

hg_experimental_functions_use_pg_implementation

时间范围扩展。to_charto_dateto_timestamp函数在处理时间类型时默认范围为1925-2282,通过设置GUC参数支持0000-9999年的时间,详情请参见类型转换函数

HologresV1.1.31版本开始支持,设置后支持时间范围为0000-9999

set hg_experimental_functions_use_pg_implementation = 'to_char';

hg_experimental_approx_count_distinct_precision

调整APPROX_COUNT_DISTINCT误差率,详情请参见APPROX_COUNT_DISTINCT

默认值为17,取值范围为12-20

set hg_experimental_approx_count_distinct_precision = 20;

timezone

时区设置。

默认值为PRC(东八区)。

set timezone='GMT-8:00';

hg_experimental_enable_create_table_like_properties

复制表时同时复制表属性(主键、索引等),详情请参见CREATE TABLE LIKE

默认值为off

set hg_experimental_enable_create_table_like_properties=true;

hg_experimental_affect_row_multiple_times_keep_first

使用insert on conflict,源数据重复时数据保留策略,详情请参见INSERT ON CONFLICT(UPSERT)

默认值为off

set hg_experimental_affect_row_multiple_times_keep_first = on;

hg_experimental_affect_row_multiple_times_keep_last

set hg_experimental_affect_row_multiple_times_keep_last = on;

hg_experimental_enable_read_replica

单实例多副本高可用以及相关配置,详情请参见单实例Shard级多副本

默认值为on

set hg_experimental_enable_read_replica = on;

hg_experimental_display_query_id

通过NOTICE消息在客户端打印Query ID,用于在hologres.hg_query_log中精确定位Query并排查问题。适用于HoloWeb、PSQL、JDBC、Python(Psycopg)等各类客户端,详情请参见获取Query ID

默认值为off。Query ID通过NOTICE消息返回,而非结果集中的一列,程序化客户端需注册相应的NOTICE回调才能获取。

set hg_experimental_display_query_id = on;

查看当前GUC参数的状态或默认值

通过show命令语句可以查看某个GUC参数的状态或者默认值,使用示例如下。

  • 查看是否开启Auto Analyze。

    show hg_enable_start_auto_analyze_worker;
  • 查看读取MaxCompute分区限制大小。

    show hg_foreign_table_max_partition_limit;
  • 查看是否开启Query ID回显。

    show hg_experimental_display_query_id;

设置GUC参数

GUC在使用时,可以设置为session级别或者数据库级别生效。

说明

具体是session级别还是数据库级别,需要根据业务场景以及参数的详情合理评估,不建议所有的参数都设置为数据库级别。

  • session级别

    通过set命令可以在session级别设置GUC参数。session级别的参数只在当前session生效,当连接断开之后,将会失效,建议加在SQL前一起执行。

    • 语法示例如下。

      set <GUC_NAME> = <VALUE>;

      GUC_NAMEGUC参数的名称,VALUEGUC参数的值。

    • 使用示例如下。

      -- 开启Auto Analyze
      set hg_enable_start_auto_analyze_worker = on;
      
      -- 读取MaxCompute的分区限制变为1024
      set hg_foreign_table_max_partition_limit =1024;
      
      -- 开启Query ID回显
      set hg_experimental_display_query_id = on;
  • 数据库级别

    可以通过alter database xx set xxx命令来设置DB级别的GUC参数,执行完成后在整个DB级别生效,设置完成后当前连接需要重新断开连接才能生效。新建DB不会生效,需要重新手动设置。

    • 语法示例如下。

      alter database <DB_NAME> set <GUC_NAME> = <VALUE>;

      DB_NAME为数据库名称,GUC_NAMEGUC参数的名称,VALUEGUC参数的值。

    • 使用示例如下。

      -- DB级别开启Auto Analyze
      alter database testdb set hg_enable_start_auto_analyze_worker = on;
      
      -- DB级别读取MaxCompute的分区限制变为1024
      alter database testdb set hg_foreign_table_max_partition_limit =1024;

获取Query ID

Query IDHologres中每条Query的唯一标识,也是慢Query日志hologres.hg_query_log的主键之一。获取某条SQL对应的Query ID后,即可精确反查该Query的耗时、状态、读取行数等执行详情,是问题排查的关键入口。

Query ID默认不返回给客户端。开启hg_experimental_display_query_id后,服务端会在执行SQL时通过NOTICE消息将Query ID回显给客户端。

参数说明

项目

说明

参数名称

hg_experimental_display_query_id

作用

执行SQL时通过NOTICE消息在客户端打印Query ID。

默认值

off

取值

onoff

生效粒度

session级别或数据库级别。

返回形式

NOTICE消息,格式为QueryID: <QUERY_ID>,例如QueryID: 1002002606817130830

使用该参数时,请注意以下两项机制:

  • Query ID通过NOTICE消息返回,而非结果集中的一列。在程序化客户端中,仅读取查询结果(如fetchall())无法获取Query ID,必须通过客户端驱动提供的NOTICE获取机制读取。

  • 该参数按session生效,连接断开后失效,每建立一个新连接都需要重新设置一次。使用连接池时需特别注意,应将set语句配置到连接初始化环节,详情请参见连接池场景

开启Query ID回显

-- session级别开启,建议与业务SQL一起执行
set hg_experimental_display_query_id = on;

-- 查看当前状态
show hg_experimental_display_query_id;

-- 数据库级别开启,对该数据库的新建连接生效,已有连接需重新建立
alter database <DB_NAME> set hg_experimental_display_query_id = on;

在客户端中获取Query ID

Java(JDBC)

JDBC中,NOTICESQLWarning链的形式返回,需要在SQL执行后通过statement.getWarnings()遍历获取并解析出Query ID,结果集ResultSet中不包含Query ID。完整示例如下。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLWarning;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class HologresQueryIdDemo {

    // 匹配NOTICE中的 "QueryID: <QUERY_ID>"
    private static final Pattern QUERY_ID_PATTERN = Pattern.compile(
            "query[_ ]?id\\s*(?:is\\b|[=:])?\\s*([0-9a-zA-Z_\\-]{6,})", Pattern.CASE_INSENSITIVE);

    public static void main(String[] args) throws Exception {
        // Endpoint请选择与运行环境匹配的网络地址(公网或VPC),在控制台的实例详情页获取
        String url = "jdbc:postgresql://<ENDPOINT>:80/<DB_NAME>";
        String user = "<ACCESS_KEY_ID>";
        String password = "<ACCESS_KEY_SECRET>";

        try (Connection conn = DriverManager.getConnection(url, user, password);
             Statement stmt = conn.createStatement()) {

            // 开启Query ID回显,该参数默认为off且仅在当前session生效
            stmt.execute("set hg_experimental_display_query_id = on;");

            String sql = "select count(*), sum(id) from holo_query_id_demo;";

            // 执行前清空上一条SQL残留的Warning,确保Query ID与SQL一一对应
            stmt.clearWarnings();
            boolean hasResultSet = stmt.execute(sql);

            // 读取结果集,Query ID不在结果集中
            if (hasResultSet) {
                try (ResultSet rs = stmt.getResultSet()) {
                    while (rs.next()) {
                        System.out.println("rows      : (" + rs.getLong(1) + ", " + rs.getLong(2) + ")");
                    }
                }
            }

            // NOTICE以SQLWarning链的形式返回,遍历并解析出Query ID
            String queryId = null;
            List<String> notices = new ArrayList<>();
            for (SQLWarning w = stmt.getWarnings(); w != null; w = w.getNextWarning()) {
                notices.add(w.getMessage());
                Matcher m = QUERY_ID_PATTERN.matcher(w.getMessage());
                if (m.find()) {
                    queryId = m.group(1);
                }
            }

            System.out.println("query_id  : " + queryId);
            System.out.println("notices   : " + notices);
        }
    }
}

返回结果示例如下。

rows      : (1000, 500500)
query_id  : 1002002606817139331
notices   : [One or more columns in the following table(s) do not have statistics: holo_query_id_demo, QueryID: 1002002606817139331]

使用时请注意以下三点:

  • PreparedStatement的用法相同,执行后调用pstmt.getWarnings()遍历即可。

  • 每次执行新的SQL前先调用clearWarnings(),否则Warning会在同一Statement对象上累积,导致Query IDSQL无法一一对应。

  • NOTICE中可能混有其他消息(例如统计信息缺失的提示),解析时应按QueryID:前缀匹配。

Python(Psycopg 3)

Hologres兼容PostgreSQL 11,推荐使用Psycopg 3驱动(通过pip install "psycopg[binary]"安装)。NOTICE需通过conn.add_notice_handler()注册回调获取,cur.fetchall()的返回结果中不包含Query ID。完整示例如下。

import re
import psycopg

NOTICES = []
QUERY_IDS = []

QUERY_ID_PATTERN = re.compile(
    r"query[_ ]?id\s*(?:is\b|[=:])?\s*([0-9a-zA-Z_\-]{6,})", re.IGNORECASE
)

def notice_handler(diag):
    """服务端每发送一条NOTICE都会回调一次,从中解析Query ID。"""
    text = diag.message_primary or ""
    NOTICES.append(text)
    match = QUERY_ID_PATTERN.search(text)
    if match:
        QUERY_IDS.append(match.group(1))

conn = psycopg.connect(
    host="<ENDPOINT>",          # 在控制台的实例详情页获取
    port=80,
    dbname="<DB_NAME>",
    user="<ACCESS_KEY_ID>",
    password="<ACCESS_KEY_SECRET>",
)
conn.autocommit = True
conn.add_notice_handler(notice_handler)   # 注册NOTICE回调

cur = conn.cursor()
# 开启Query ID回显,该参数默认为off且仅在当前session生效
cur.execute("set hg_experimental_display_query_id = on;")

def run_sql(sql, params=None, fetch=True):
    """执行SQL并返回 (结果集, Query ID, 原始NOTICE列表)。无结果集时结果集为None。"""
    NOTICES.clear()
    QUERY_IDS.clear()
    cur.execute(sql, params)
    rows = None
    if fetch and cur.description is not None:
        rows = cur.fetchall()
    query_id = QUERY_IDS[-1] if QUERY_IDS else None
    return rows, query_id, list(NOTICES)

rows, query_id, notices = run_sql("select count(*) from holo_query_id_demo;")
print("rows:", rows)
print("query_id:", query_id)

返回结果示例如下,DMLDQL均可获取Query ID。

SQL       : insert into holo_query_id_demo select i, 'v' || i from generate_series(1, 1000) i;
query_id  : 1002002606817130830
notices   : ['QueryID: 1002002606817130830']

SQL       : select count(*), sum(id) from holo_query_id_demo;
query_id  : 1002002606817139331
rows      : [(1000, 500500)]
notices   : ['One or more columns in the following table(s) do not have statistics: holo_query_id_demo', 'QueryID: 1002002606817139331']

连接池场景

该参数按session生效,每条物理连接都需要设置一次。使用连接池时,应将set语句配置到连接建立(初始化)环节,而不是在每次查询前手动执行。

Pythonpsycopg_pool为例,示例如下。

# 需先执行 pip install psycopg_pool
from psycopg_pool import ConnectionPool

def configure(conn):
    conn.autocommit = True
    conn.add_notice_handler(notice_handler)
    conn.execute("set hg_experimental_display_query_id = on;")

pool = ConnectionPool(kwargs=CONN_INFO, configure=configure, min_size=1, max_size=4)

with pool.connection() as conn:
    conn.execute("select 1;").fetchall()

Java通过连接池的初始化SQL配置,保证每条物理连接建立时都已开启该参数。以HikariCPDruid为例,示例如下。

// HikariCP:connectionInitSql在每条物理连接建立时执行
HikariConfig config = new HikariConfig();
config.setJdbcUrl(url);
config.setUsername(user);
config.setPassword(password);
config.setConnectionInitSql("set hg_experimental_display_query_id = on;");
HikariDataSource dataSource = new HikariDataSource(config);

// Druid:connectionInitSqls支持配置多条初始化SQL
DruidDataSource druid = new DruidDataSource();
druid.setUrl(url);
druid.setUsername(user);
druid.setPassword(password);
druid.setConnectionInitSqls(Collections.singletonList("set hg_experimental_display_query_id = on;"));

从连接池获取连接后,仍需在每次执行SQL后通过statement.getWarnings()获取Query ID,获取方式请参见Java(JDBC)

通过Query ID反查执行详情

获取Query ID后,可在慢Query日志中按query_id精确定位该Query的耗时、状态、读取行数等信息。

select query_id, status, duration, query_start, application_name, command_tag
from hologres.hg_query_log
where query_id = '<QUERY_ID>';

hologres.hg_query_log存在约1分钟的写入延迟,Query刚执行完可能查询不到,请稍后重试。

注意事项

  • 该参数按session生效,连接断开后失效。每建立一个新连接都必须重新执行set hg_experimental_display_query_id = on;,否则该连接上的Query不会回显Query ID。

  • 并非所有语句都会返回Query ID。DDL语句(如CREATE TABLEDROP TABLE)以及不涉及计算引擎的简单查询(如select 1;)不返回Query ID,属于预期行为;DML语句(如INSERT)与常规查询(如SELECT)可正常返回。

  • NOTICE中可能同时包含其他提示消息(例如统计信息缺失的警告),程序解析时应按QueryID:前缀精确匹配,避免误取。

无法获取Query ID时如何排查

请按以下顺序确认。

  1. 执行show hg_experimental_display_query_id;确认参数是否为on。若为off,说明当前连接未执行过set(使用连接池时可能已切换到其他连接),请重新设置或检查连接初始化逻辑。

  2. 检查NOTICE缓冲区是否为空。若为空,说明服务端未发送NOTICE,请确认实例版本是否支持该参数,或确认该语句类型是否会产生Query ID。

  3. NOTICE有内容但未解析出Query ID,说明消息措辞与解析规则不匹配,请打印NOTICE原始文本,并按实例实际返回的格式调整解析逻辑。

  4. 使用连接池时,请确认set语句已配置到连接初始化环节,保证每条物理连接都已执行。