ANALYZE和AUTO ANALYZE
本文將為您介紹如何使用Analyze命令,以及更加簡單的Auto Analyze的相關機制。
Analyze
統(tǒng)計信息決定是否能夠生成正確的執(zhí)行計劃。Hologres需要收集數(shù)據(jù)的采樣統(tǒng)計信息,包括數(shù)據(jù)的分布和特征、表的統(tǒng)計信息、列的統(tǒng)計信息、行數(shù)、列數(shù)、字段寬度、基數(shù)、頻度、最大值、最小值、高頻值、分桶分布特征等信息。這些信息將為優(yōu)化器更新算子執(zhí)行預估COST、搜索空間裁剪、估算最優(yōu)JOIN ORDER、估算內(nèi)存開銷、估算并行度,從而生成更優(yōu)的執(zhí)行計劃。
Analyze命令用于收集數(shù)據(jù)庫中表內(nèi)容的統(tǒng)計信息,優(yōu)化器會根據(jù)這些統(tǒng)計信息生成最佳的查詢計劃,從而提高查詢效率。
使用語法
-- 更新某個表的統(tǒng)計信息,默認會收集表中所有列的統(tǒng)計信息 analyze <tablename>; -- 更新某個列的統(tǒng)計信息,會比更新表時采樣的數(shù)據(jù)更多,更精準,主要用于更新管理條件的列 analyze <tablename>(<colname>, <colname>);
參數(shù)說明
tablename為更新統(tǒng)計信息的表名稱,colname為更新統(tǒng)計信息的列名稱。
語法說明
兩個Analyze命令的說明如下。
相同點
對列統(tǒng)一收集包括行數(shù)、列寬、列的最常用值(Most Common Values)、列的直方圖(Histogram)信息,列的非重復值的個數(shù)(Number of Distinct Value,NDV)在內(nèi)的信息。
兩個命令都會相互覆蓋指定列的統(tǒng)計信息,但不會覆蓋其他列的信息。例如
analyze <tablename>(<colname1>);
命令會覆蓋(更新)之前colname1
列收集的統(tǒng)計信息,但并不會改變colname2
列的統(tǒng)計信息。
不同點
analyze <tablename>;
基于采樣數(shù)據(jù),計算得出統(tǒng)計信息。analyze <tablename>(<colname>, <colname>);
會對列的Number of Distinct Value(NDV)進行APPROX_COUNT_DISTINCT計算,在很多情況下,這樣計算的值相比采樣更準確,但開銷比采樣表更大,因此只適合對重點列進行指定ANALYZE。NDV以外的Histogram、Width等信息,仍然通過采樣得到。
因此對于具有兩列的
table (colname1, colname2)
,analyze table;
不完全等價于analyze table(colname1, colname2);
。對于常用的Join列、Group By列,推薦使用
analyze <tablename>(<colname>, <colname>);
命令進行額外的統(tǒng)計信息收集。
需要執(zhí)行Analyze的情況
推薦您在如下情況下運行
analyze <tablename>;
命令。在表執(zhí)行大量的INSERT、UPDATE以及DELETE操作之后,包括導入數(shù)據(jù)。
在性能下降的情況下,多表Join查詢之前,對Join的列、Group by的列進行Analyze。
執(zhí)行
CREATE FOREIGN TABLE
命令后,通過Analyze收集當前外部表統(tǒng)計信息。執(zhí)行
IMPORT FOREIGN SCHEMA
后,對后續(xù)需要查詢的表進行Analyze。
注意事項
在Hologres V0.10和V1.1版本中,如果有對父表的查詢,需要Analyze分區(qū)父表;如果直接對子表查詢,請對子表Analyze;如果兩者都有,建議兩者都進行Analyze,否則可能會有缺失統(tǒng)計信息的情況。
如果遇到以下問題,您需要先執(zhí)行Analyze,再運行導入任務,可以系統(tǒng)地提升效率。
多表JOIN超出內(nèi)存OOM:通常會產(chǎn)生
Query executor exceeded total memory limitation xxxxx: yyyy bytes used
報錯。導入效率較低:在Hologres查詢或?qū)霐?shù)據(jù)時,效率較低,運行的任務長時間不結束。
如果有超寬列(例如Bitmap等Bytea數(shù)據(jù),超過1KB的Text數(shù)據(jù)等),這些超寬列的統(tǒng)計信息沒有作用,還會使采樣更消耗內(nèi)存。因此對于具有上述超寬列的表,盡量避免執(zhí)行
analyze <tablename>;
命令,而是采用analyze <tablename>(<colname>, <colname>);
避開超寬列,轉為Analyze必要的列(例如上面推薦的Join的列、Group by的列和Filter列等)。說明1KB是經(jīng)驗值,寬度標準可以根據(jù)業(yè)務情況自行決定。
Auto Analyze
為了減少重復、手動的Analyze,從Hologres V0.10版本開始,支持Auto Analyze機制。開啟auto analyze后,系統(tǒng)會根據(jù)用戶的建表、數(shù)據(jù)寫入和修改情況等來判斷是否需要對相關的表在后臺自動Analyze,無需再手動對表進行Analyze,降低操作復雜度,同時減少遺漏Analyze而導致缺失統(tǒng)計信息的情況。
使用語法
查看是否開啟Auto Analyze
SHOW hg_enable_start_auto_analyze_worker; -- V1.1及以上版本語法,查看當前開啟/關閉狀態(tài) SHOW hg_experimental_enable_start_auto_analyze_worker; -- V0.10語法,查看當前開啟/關閉狀態(tài)
開啟/關閉語法如下,需要Superuser執(zhí)行。
-- DB級別,執(zhí)行后整個DB生效,V1.1及以上版本開啟/關閉語法 ALTER DATABASE dbname SET hg_enable_start_auto_analyze_worker = ON; -- 開啟(默認) ALTER DATABASE dbname SET hg_enable_start_auto_analyze_worker = OFF; -- 關閉 -- DB級別,執(zhí)行后整個DB生效,V0.10開啟/關閉語法 ALTER DATABASE dbname SET hg_experimental_enable_start_auto_analyze_worker = ON; -- 開啟(默認) ALTER DATABASE dbname SET hg_experimental_enable_start_auto_analyze_worker = OFF; -- 關閉
使用限制
在Hologres中使用Auto Analyze,具體限制如下:
Auto Analyze功能僅Hologres V0.10及以上版本支持,請在Hologres管理控制臺的實例詳情頁查看當前版本,如果您的實例是V0.10以下版本,請您使用自助升級或加入Hologres釘釘交流群反饋,詳情請參見如何獲取更多的在線支持?。
僅支持Superuser執(zhí)行開啟或關閉Auto Analyze操作。
Auto Analyze對分區(qū)表的限制如下。
分區(qū)子表發(fā)生改變,需要Auto Analyze時,會統(tǒng)一Analyze其父表。
分區(qū)表有掃描行數(shù)限制,采樣數(shù)據(jù)時默認掃描的最大記錄數(shù)是224條(16,777,216條),即若所有分區(qū)子表的記錄數(shù)總和超過16,777,216條,會做一定的分區(qū)裁剪,只對其中若干分區(qū)(總和不超過16,777,216條)進行采樣。
說明分區(qū)列統(tǒng)計信息總是全的,不受裁剪影響,但是這可能會影響與分區(qū)列同分布的列(例如極端情況是,與分區(qū)列數(shù)據(jù)一樣的列)的統(tǒng)計信息,即一部分值采樣不到,行數(shù)估計可能不準確。如果有需求可以搜索(釘釘群號:32314975)加入實時數(shù)倉Hologres交流群聯(lián)系技術支持,技術側根據(jù)實例情況評估調(diào)整掃描的最大記錄數(shù)。
Auto Analyze默認最大收集256列的統(tǒng)計信息,如表超過256列,取前256列。可通過調(diào)整
hg_experimental_auto_analyze_max_columns_count
改變此值。Auto Analyze默認單個Worker限制的內(nèi)存是4 GB,如果存在超寬的列,采樣可能超出內(nèi)存而導致Analyze失敗??烧{(diào)整
auto_analyze_work_memory_mb
參數(shù)改變其大小,但是要注意對系統(tǒng)內(nèi)存的影響。實例規(guī)格越大,Worker數(shù)越多,Auto Analyze可用內(nèi)存限制越大。
Auto Analyze工作原理
當開始Auto Analyze后,系統(tǒng)后臺會定期巡檢是否有表需要執(zhí)行Analyze。
普通表(內(nèi)部表,包括單表和分區(qū)表)
每隔1分鐘巡檢是否有表的最新動作(主要是INSERT、UPDATE、DELETE等DML操作,可能改變了數(shù)據(jù)量)。滿足以下條件,系統(tǒng)后臺觸發(fā)表的Analyze,收集表的統(tǒng)計信息。
表有DML執(zhí)行完成且數(shù)據(jù)條數(shù)變化超過當前表的數(shù)據(jù)條數(shù)的10%。若表是分區(qū)子表,則是指變化條數(shù)超過此分區(qū)數(shù)據(jù)條數(shù)的10%。
TRUNCATE TABLE清空表。
表的DDL發(fā)生變更。例如CREATE TABLE新建表,ALTER TABLE修改表結構等,不包括CALL SET_TABLE_PROPERTY修改表屬性。
每隔10分鐘檢測所有內(nèi)部表的數(shù)據(jù)變化,如果滿足數(shù)據(jù)條數(shù)變化超過上一次檢測的10%,則后臺觸發(fā)該表的Analyze。
說明這一步驟是為了檢測到非顯式DML(例如通過Flink、數(shù)據(jù)集成、HoloClient實時寫入)更新的數(shù)據(jù)。
外部表
當前僅支持Analyze MaxCompute外部表,其他引擎的外部表暫不支持Analyze和Auto Analyze。
每隔4小時定期巡檢外部表元數(shù)據(jù)或數(shù)據(jù)變化情況。滿足以下條件,系統(tǒng)后臺觸發(fā)表的Analyze,收集統(tǒng)計信息。
外部表對應的外部系統(tǒng)的表(例如MaxCompute表)在兩次巡檢間隔(例如4小時內(nèi))改變過,改變的標準是對應MaxCompute表的
last_modify_time
處于巡檢間隔之間。
說明巡檢和執(zhí)行在同一個調(diào)度任務中,所以下一次巡檢調(diào)度開始依賴Analyze執(zhí)行結束,只要離上一次開始巡檢的時間滿足調(diào)度周期,就可以進入下一次巡檢。
配置參數(shù)
開啟Auto Analyze后,系統(tǒng)默認會自動周期性巡檢,決定需要執(zhí)行Analyze的表,并進行采樣計算,收集統(tǒng)計信息,對系統(tǒng)資源有一定的消耗。
在某些業(yè)務場景下,默認的機制可能不適用于業(yè)務場景,例如數(shù)據(jù)寫入更新不頻繁場景,可以通過修改默認參數(shù)來減少自動Analyze的頻率。諸如此類可以根據(jù)業(yè)務情況更改默認參數(shù),以此達到部分性能調(diào)優(yōu)的目的。
說明只有Superuser能調(diào)整Auto Analyze的默認行為,且都需要數(shù)據(jù)庫級別設置參數(shù),且在下一分鐘后生效。
使用語法
--Superuser修改Auto Analyze參數(shù)的默認值 ALTER DATABASE <dbname> SET <GUC>=<values>;
dbname為數(shù)據(jù)庫名稱;GUC為參數(shù)名稱;values為參數(shù)值。
參數(shù)列表
參數(shù)
參數(shù)描述
支持版本
默認值
使用示例
autovacuum_naptime
巡檢是否有表的最新動作的周期,單位是秒(s)。
V1.1.0及以上版本
說明需后臺調(diào)整,如需調(diào)整請搜索(釘釘群號:32314975)加入實時數(shù)倉Hologres交流群申請。
60s
ALTER DATABASE <dbname> SET autovacuum_naptime = 60;
ALTER DATABASE <dbname> SET autovacuum_naptime = '60s';
ALTER DATABASE <dbname> SET autovacuum_naptime = '10min';
hg_auto_check_table_changes_interval
檢查所有內(nèi)部表的數(shù)據(jù)變化的周期,單位是秒(s)。
V1.1.0及以上版本
600s(10min)
--V1.1及以上版本命令語法 ALTER DATABASE <dbname> SET hg_auto_check_table_changes_interval = '600s'; --V0.10版本命令語法 ALTER DATABASE <dbname> SET hg_experimental_auto_check_table_changes_interval = '600s';
hg_auto_check_foreign_table_changes_interval
檢查所有外部表的數(shù)據(jù)變化的周期,單位是秒(s)。
V1.1.0及以上版本
14400s(4小時)
--V1.1及以上版本命令語法 ALTER DATABASE <dbname> SET hg_auto_check_foreign_table_changes_interval = '14400s'; --V0.10版本命令語法 ALTER DATABASE <dbname> SET hg_experimental_auto_check_foreign_table_changes_interval = '14400s';
hg_experimental_auto_analyze_max_columns_count
自動收集統(tǒng)計信息的列數(shù),單位是個。
V1.1.0及以上版本
256個
ALTER DATABASE <dbname> SET hg_experimental_auto_analyze_max_columns_count =300;
auto_analyze_work_memory_mb
Auto Analyze單個表的內(nèi)存限制,單位是MB。
V1.1.54及以上版本
默認單個Worker 4096 MB,即4GB,實例規(guī)格越大,Worker越多,真實內(nèi)存限制越大。
Auto Analyze單個表的內(nèi)存限制修改為9GB。
ALTER DATABASE <dbname> SETauto_analyze_work_memory_mb =9216;
hg_experimental_auto_analyze_start_time
Auto-Analyze在每天運行的開始時間
說明需要與end_time是同一時區(qū),并且start time要小于等于end_time。
V1.1.54及以上版本
00:00 +0800
修改為僅需要在0~6點執(zhí)行Auto-Analyze,白天內(nèi)外部表數(shù)據(jù)不變,無需Analyze的情況。
ALTER DATABASE <dbname> SET hg_experimental_auto_analyze_start_time = '00:00 +0800';
ALTER DATABASE <dbname> SET hg_experimental_auto_analyze_end_time = '06:00 +0800';
hg_experimental_auto_analyze_end_time
Auto Analyze在每天運行的結束時間。
V1.1.54及以上版本
23:59 +0800
autovacuum_enabled
表Auto Analyze的開啟狀態(tài)。
V1.1.54及以上版本
true,即默認全部開啟。
關閉某表的Auto Analyze,以后Analyze將跳過此表。
說明僅支持使用如下命令為Hologres內(nèi)部表關閉Auto Analyze。
ALTER TABLE <tablename> SET (autovacuum_enabled = false);
查詢統(tǒng)計信息
表的統(tǒng)計信息被記錄在hologres_statistic.hg_table_statistic表中,可以通過檢查該表信息了解Analyze的狀態(tài),命令如下。
如果需要查最近一次Analyze的信息,根據(jù)analyze_timestamp
排序即可。
SELECT schema_name, -- 表的Schema
table_name, -- 表名稱
schema_version, -- 表的版本
statistic_version, -- 最近一次ANALYZE的統(tǒng)計信息版本
total_rows, -- 最近一次ANALYZE的行數(shù)
analyze_timestamp -- 最近一次ANALYZE的結束時間
FROM hologres_statistic.hg_table_statistic
WHERE table_name = '<tablename>'
ORDER BY analyze_timestamp DESC;
每個表在hologres_statistic.hg_table_statistic表中有
0~n
條記錄。0條表示從未進行過Analyze,1條及以上表示運行過Analyze。若出現(xiàn)兩條及以上的情況,兩條記錄的schema_version一定不一樣,因為表的Schema變化了(例如執(zhí)行
ADD COLUMN
等命令會產(chǎn)生新的版本),會增加一條統(tǒng)計信息記錄,老的schema_version對應的記錄不再被使用。示例查詢結果如下,同一個表有兩條記錄,而第二條記錄的schema_version低于第一條,那么第二條將作廢,不會被使用,也無需關注。
schema_name | table_name | schema_version | statistic_version | total_rows | analyze_timestamp -------------+------------------+----------------+-------------------+------------+--------------------- public | tbl_name_example | 13 | 8580 | 10002 | 2022-04-29 16:03:18 public | tbl_name_example | 10 | 8576 | 10002 | 2022-04-29 15:41:20 (2 rows)
Hologres V0.10和V1.1版本暫不會清理hg_table_statistic表中的歷史過期記錄,同時不用關心老的數(shù)據(jù)。
查看缺失統(tǒng)計信息的表
通過HG_STATS_MISSING視圖,可以查看當前數(shù)據(jù)庫中缺失統(tǒng)計信息的表,詳情請參見HG_STATS_MISSING View。
常見問題
出現(xiàn)如下情況,代表Auto Analyze工作未正常,請參照解決方法進行處理。
表的統(tǒng)計信息是0條
問題現(xiàn)象:通過hologres_statistic.hg_table_statistic表查看表的統(tǒng)計信息,沒有數(shù)據(jù)。
可能原因:
Auto Analyze沒有工作,或者該表不符合Auto Analyze觸發(fā)條件。
Auto Analyze本身的問題導致,需要搜索(釘釘群號:32314975)加入實時數(shù)倉Hologres交流群詢問專業(yè)人員具體排查原因。
解決方法:手動觸發(fā)一次Analyze。
analyze_timestamp
過小問題現(xiàn)象:查詢結果中
analyze_timestamp
過?。幢犬斍皶r間小很多),代表長時間沒有進行過Analyze。可能原因:
某種原因未能正常執(zhí)行Auto Analyze。
手動關閉過Auto Analyze。
解決方法:先手動觸發(fā)Analyze,再搜索(釘釘群號:32314975)加入實時數(shù)倉Hologres交流群詢問專業(yè)人員排查原因。