為了更好地支援Hologres使用者豐富的使用情境,Hologres提供一些GUC參數。本文將介紹Hologres中GUC參數的含義以及如何使用。
使用限制
GUC參數對系統資料表不生效。
GUC參數一覽表
GUC名稱 | 適用情境 | 說明 | 使用樣本 |
hg_enable_start_auto_analyze_worker | 開啟Auto Analyze,以及Auto Analyze相關配置,詳情請參見ANALYZE和AUTO ANALYZE。 | HologresV1.1及以上版本預設開啟,值為 | set hg_enable_start_auto_analyze_worker = on; |
hg_auto_check_table_changes_interval | 預設值為 | set hg_auto_check_table_changes_interval = '10min'; | |
hg_auto_check_foreign_table_changes_interval | 預設值為 | set hg_auto_check_foreign_table_changes_interval = '4h'; | |
hg_auto_analyze_max_sample_row_count | 預設值為 | set hg_auto_analyze_max_sample_row_count = 16777216; | |
hg_fixed_api_modify_max_delay_interval | 預設值為 | set hg_fixed_api_modify_max_delay_interval = '3day'; | |
hg_foreign_table_max_partition_limit | 查MaxCompute外部表格分區限制。如需調整限制可通過該GUC參數進行設定。 |
| set hg_foreign_table_max_partition_limit = 128; |
hg_experimental_query_batch_size | MaxCompute效能調優參數,詳情請參見最佳化MaxCompute外部表格的查詢效能。 | 預設值為 | set hg_experimental_query_batch_size = 4096; |
hg_foreign_table_split_size | 預設值為 | set hg_foreign_table_split_size = 128; | |
hg_foreign_table_executor_max_dop | 預設值調整為與執行個體Core數相同,最大為 | set hg_foreign_table_executor_max_dop = 32; | |
hg_foreign_table_executor_dml_max_dop | 預設值為 | set hg_foreign_table_executor_dml_max_dop = 16; | |
hg_enable_access_odps_orc_via_holo | HologresV1.1及以上版本預設開啟,值為 | set hg_enable_access_odps_orc_via_holo = on; | |
hg_experimental_enable_result_cache | 查詢結果緩衝。 | 預設值為 | set hg_experimental_enable_result_cache = on; |
optimizer_join_order | 內部效能調優參數,詳情請參見最佳化查詢效能。 | 預設值為 | set optimizer_join_order = query; |
optimizer_force_multistage_agg | 預設值為 | set optimizer_force_multistage_agg = on; | |
hg_anon_enable | 資料脫敏函數,詳情請參見資料脫敏。 | 預設值為 | alter database <DB_NAME> set hg_anon_enable = on; |
hg_experimental_encryption_options | 資料加密規格設定,詳情請參見資料存放區加密。 | 預設值為 | alter database <DB_NAME> set hg_experimental_encryption_options='AES256,623c26ee-xxxx-xxxx-xxxx-91d323cc4855,AliyunHologresEncryptionDefaultRole,187xxxxxxxxxxxxx'; |
statement_timeout | 活躍query逾時時間,詳情請參見管理Query。 | 預設值為 | set statement_timeout = 5000 ; |
idle_in_transaction_session_timeout | 空閑事務的逾時時間,詳情請參見管理Query。 | 預設值為 | alter database db_name set idle_in_transaction_session_timeout=300000; |
idle_session_timeout | 自動釋放空閑連線逾時時間,詳情請參見串連數管理。 | 預設值為 | alter database <DB_NAME> SET idle_session_timeout = 600000; |
hg_experimental_functions_use_pg_implementation | 時間範圍擴充。 | HologresV1.1.31版本開始支援,設定後支援時間範圍為 | set hg_experimental_functions_use_pg_implementation = 'to_char'; |
hg_experimental_approx_count_distinct_precision | 調整APPROX_COUNT_DISTINCT誤差率,詳情請參見APPROX_COUNT_DISTINCT。 | 預設值為 | set hg_experimental_approx_count_distinct_precision = 20; |
timezone | 時區設定。 | 預設值為 | set timezone='GMT-8:00'; |
hg_experimental_enable_create_table_like_properties | 複製表時同時複製表屬性(主鍵、索引等),詳情請參見CREATE TABLE LIKE。 | 預設值為 | set hg_experimental_enable_create_table_like_properties=true; |
hg_experimental_affect_row_multiple_times_keep_first | 使用 | 預設值為 | 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級多副本。 | 預設值為 | set hg_experimental_enable_read_replica = on; |
hg_experimental_display_query_id | 通過NOTICE訊息在用戶端列印Query ID,用於在 | 預設值為 | 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_NAME為GUC參數的名稱,VALUE為GUC參數的值。
使用樣本如下。
-- 開啟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_NAME為GUC參數的名稱,VALUE為GUC參數的值。
使用樣本如下。
-- 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 ID是Hologres中每條Query的唯一標識,也是慢Query日誌hologres.hg_query_log的主鍵之一。擷取某條SQL對應的Query ID後,即可精確反查該Query的耗時、狀態、讀取行數等執行詳情,是問題排查的關鍵入口。
Query ID預設不返回給用戶端。開啟hg_experimental_display_query_id後,服務端會在執行SQL時通過NOTICE訊息將Query ID回顯給用戶端。
參數說明
專案 | 說明 |
參數名稱 |
|
作用 | 執行SQL時通過NOTICE訊息在用戶端列印Query ID。 |
預設值 |
|
取值 |
|
生效粒度 | session層級或資料庫層級。 |
返回形式 | NOTICE訊息,格式為 |
使用該參數時,請注意以下兩項機制:
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中,NOTICE以SQLWarning鏈的形式返回,需要在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 ID與SQL無法一一對應。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)返回結果樣本如下,DML與DQL均可擷取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語句配置到串連建立(初始化)環節,而不是在每次查詢前手動執行。
Python以psycopg_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配置,保證每條物理串連建立時都已開啟該參數。以HikariCP和Druid為例,樣本如下。
// 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 TABLE、DROP TABLE)以及不涉及計算引擎的簡單查詢(如select 1;)不返回Query ID,屬於預期行為;DML語句(如INSERT)與常規查詢(如SELECT)可正常返回。NOTICE中可能同時包含其他提示訊息(例如統計資訊缺失的警告),程式解析時應按
QueryID:首碼精確匹配,避免誤取。
無法擷取Query ID時如何排查
請按以下順序確認。
執行
show hg_experimental_display_query_id;確認參數是否為on。若為off,說明當前串連未執行過set(使用串連池時可能已切換到其他串連),請重新設定或檢查串連初始化邏輯。檢查NOTICE緩衝區是否為空白。若為空白,說明服務端未發送NOTICE,請確認執行個體版本是否支援該參數,或確認該語句類型是否會產生Query ID。
若NOTICE有內容但未解析出Query ID,說明訊息措辭與解析規則不匹配,請列印NOTICE原始文本,並按執行個體實際返回的格式調整解析邏輯。
使用串連池時,請確認set語句已配置到串連初始化環節,保證每條物理串連都已執行。