本文為您介紹Hologres監控指標相關的常見問題。
- 串連數過多時如何查看有哪些串連以及Kill串連?
- 查詢延遲過高時如何解決?
- 記憶體使用量率高的原因及解決方案?
- 為什麼只有一個任務,Hologres執行個體CPU使用率就達到100%?
- 寫入慢如何解決?
- CPU使用率長期達到100%如何解決?
- 正在運行Query時間長度較長如何解決?
- 失敗Query如何排查?
- Worker CPU負載不均如何解決?
串連數過多時如何查看有哪些串連以及Kill串連?
- 產生
FATAL: sorry, too many clients already connection limit exceeded for superusers
報錯。 - 產生
FATAL: remaining connection slots are reserved for non-replication superuser connections
報錯。
查詢延遲過高時如何解決?
- QPS較低,但查詢SQL較複雜,導致查詢延遲高。
解決方案:對SQL進行最佳化,設定合理的索引,以提高查詢效能,詳情請參見最佳化查詢效能和最佳化MaxCompute外部表格的查詢效能。
- 查詢的QPS較高,導致查詢延遲較高。
解決方案:若是SQL已經最佳化完畢,但需要更高的QPS以及更低的延遲,可以擴容執行個體,用更多的資源擷取更好的效能,詳情請參見執行個體升配。
- 查詢時還有大量的寫入,寫入影響查詢,導致查詢延遲高。解決方案:寫入影響了查詢效能,可以進行如下操作。
- 寫入在查詢低峰期進行,降低對查詢的影響。
- 降低寫入的並發度,提高查詢效率,如果是外表寫入,可以用以下參數降低並發度。
--設定MaxCompute執行的最大並發度,預設為128,建議數值設定小一些,避免一個Query影響其他Query,導致系統繁忙導致報錯。 set hg_experimental_foreign_table_executor_max_dop = 32; --優先考慮設定 --調整每次讀取MaxCompute表batch的大小,預設8192。 set hg_experimental_query_batch_size = 1024; --直讀orc set hg_experimental_enable_access_odps_orc_via_holo = on; --設定MaxCompute表訪問切分spilit的數目,可以調節並發數目,預設64MB,當表很大時需要調大,避免過多的split影響效能。 set hg_experimental_foreign_table_split_size = 512MB;
記憶體使用量率高的原因及解決方案?
Hologres執行個體的記憶體使用量率為記憶體綜合使用率。Hologres的記憶體資源採用預留模式,在沒有查詢的時候,也會有資料表的中繼資料、索引、資料緩衝等載入到記憶體中,以便加快檢索和計算,此時記憶體使用量率不為零是正常情況。理論上在無查詢的情況,記憶體使用量率達到30%~40%左右都屬於正常現象。
- 表越來越多,資料總量越來越大,以至於資料規模遠大於當前計算規格。由於記憶體使用量率和中繼資料、索引量存在正相關關係,因此,表的數量越多,資料量越大,索引越多,都會導致記憶體使用量率升高。
- 索引不合理,例如表的列特別多,TEXT列居多,設定了過多的Bitmap或Dictionary索引。此情況可以考慮去掉一些Bitmap或者Dictionar索引,詳情請參見ALTER TABLE。
但是當記憶體使用量率穩定增長,長期接近80%時,通常意味著記憶體資源可能成為了系統的瓶頸,可能會影響執行個體的穩定性和或效能。穩定性影響體現在當中繼資料等過大,超額佔據了正常Query可用的記憶體空間時,在查詢過程中,可能會偶發SERVER_INTERNAL_ERROR
、ERPC_ERROR_CONNECTION_CLOSED
、Total memory used by all existing queries exceeded memory limitation
等報錯。效能影響體現在當中繼資料等過大,超額佔據了正常Query本來能夠使用的緩衝空間,從而快取命中會減少,Query延遲會增加。
- 刪除不再查詢的資料,以釋放中繼資料等占的記憶體。
- 設定合理的索引,若是業務情境用不上的bitmap和dictionary,可以去掉,但不建議直接去掉,需要根據業務情況具體分析。
- 升配執行個體的計算和儲存資源。對於升配的建議是:
- 普通情境:可以容許讀磁碟資料的延遲,回應時間要求不嚴格,1CU(1Core+4GB記憶體)可以支援50~100GB的資料存放區。
- 回應時間要求低的Serving情境:最好查詢熱點資料全在記憶體的緩衝中。記憶體中緩衝的比例預設佔總記憶體的30%,即1CU(1Core+4GB記憶體)其中1.3GB用於資料緩衝,同時資料緩衝還會被表的中繼資料所使用一些。舉個例子,低響應要求的情境,熱點資料如果是100GB,那麼最好要求100GB 在緩衝可用(實際上資料讀出來解壓後,佔用記憶體不止100GB),因此至少需要約320GB記憶體以上,從而推算計算資源至少需要96CU左右。
為什麼只有一個任務,Hologres執行個體CPU使用率就達到100%?
Hologres執行個體的CPU使用率為執行個體的CPU綜合使用率。Hologres因其可以充分發揮多核並行計算的能力,通常來說單個查詢可以迅速將CPU使用率提高到100%,這說明計算資源得到了充分利用。CPU使用率高不是問題,CPU使用率高了之後,查詢慢寫入慢才是問題,需要綜合分析。
寫入慢如何解決?
執行insert
、insert on conflict
或update
命令時,耗時比較長即寫入效能較差,通常原因是因為SQL沒有走Fixed Plan,沒有走Fixed Plan的SQL命令存在表鎖,並發執行時會等鎖,導致耗時較長,即時寫入RPS
監控指標會顯示寫入類型為insert
。可以查看Query的特徵改寫為走Fixed Plan的方式,讓監控指標的寫入類型變成SDK
提升寫入效能,詳情請參加Fixed Plan加速SQL執行。
CPU使用率長期達到100%如何解決?
- 排查一:QPS或者RPS明顯上漲。
對比CPU使用率上漲前和上漲後的QPS和RPS監控指標,如果有明顯的上漲趨勢,而導致CPU使用率上漲。
解決方案如下。- 查詢資料(select)行為導致CPU使用率上漲,可以通過慢Query日誌,排查耗時較長的Query,對Query進行針對性最佳化。
- 執行
insert
、update
或delete
操作導致CPU使用率上漲,建議通過慢Query日誌排查Query是否未走Fixed Plan,如下SQL所示。未走Fixed Plan的insert
、update
或delete
命令會產生表鎖,Query並發會造成鎖等待,可以從業務上判斷是否可以改寫為走Fixed Plan的SQL,避免表鎖,降低CPU水位。--樣本查看過去一小時未走fixed plan的insert/update/delete select * from hologres.hg_query_log where query_start >= now() - interval '3 h' and command_tag in ('INSERT','UPDATE','DELETE') and 'HQE'=ANY(engine_type) order by query_start desc limit 500;
- SQL都已經合理,但是CPU使用率還是比較高,說明執行個體資源已到瓶頸,可以適當的擴容或者使用多執行個體共用儲存部署從而讀寫分離,詳情請參見執行個體升配或主從執行個體讀寫分離部署(共用儲存)。
- 排查二:未有明顯的QPS或者RPS上漲,存在已耗用時間較長的Query。通過監控指標發現沒有明顯的QPS或者RPS上漲,但是CPU使用率卻突然上漲並且持續一段時間,可以通過
正在運行Query持續時間長度
監控指標查看是否有已耗用時間較長的Query,若監控指標顯示有運行時間長度超過半個小時或者一小時的Query,說明是該Query導致的CPU使用率高。使用如下命令通過活躍Query查詢啟動並執行Query,並結束Query,從而降低CPU使用率。--查看已耗用時間較長的query SELECT current_timestamp - query_start as runtime, datname::text, usename, query, pid::text FROM pg_stat_activity WHERE state != 'idle' order by 1 desc; --取消query執行 select pg_cancel_backend(<pid>);
- 排查三:未有明顯的QPS或者RPS上漲,存在耗時較長的Query。通過監控指標發現沒有明顯的QPS或者RPS上漲,但是CPU使用率卻突然上漲並且持續一段時間,可以通過如下命令從慢Query日誌查看消耗CPU較高的Query,從而定位CPU消耗的操作,並根據Query最佳化SQL。
-- 查詢最近3小時消耗比較高的Query select status as "狀態", duration as "耗時(ms)", query_start as "開始時間", (read_bytes/1048576)::text || ' MB' as "讀取量", (memory_bytes/1048576)::text || ' MB' as "記憶體", (shuffle_bytes/1048576)::text || ' MB' as "Shuffle", (cpu_time_ms/1000)::text || ' s' as "CPU時間", physical_reads as "讀盤量", query_id as "QueryID", query from hologres.hg_query_log where query_start > current_timestamp - interval'3 h' and command_tag in ('SELECT','INSERT','UPDATE','DELETE') and duration > 1000 order by duration desc, read_bytes desc, shuffle_bytes desc, memory_bytes desc, cpu_time_ms desc, physical_reads desc limit 500;
- 排查四:PQE的SQL導致CPU使用率達到100%。通過監控指標發現未有明顯的QPS或者RPS上漲,可以使用如下SQL命令從慢Query日誌查詢是否有新增的PQE SQL,導致CPU使用率上漲。如果存在PQE SQL,則需要最佳化SQL中走PQE引擎的運算元,詳情請參見最佳化查詢效能。
--查詢最近3小時走PQE的query select * from hologres.hg_query_log where query_start > current_timestamp - interval'3 h' and 'PQE'=ANY(engine_type) order by query_start desc limit 500;
- 排查五:對錶修改過Bitmap或者Dictionary索引。對錶修改過Bitmap或者Dictionary索引,修改後會觸發後台非同步執行Compaction,佔用一定的CPU資源,同時執行個體的儲存量可能會出現先上升後回落的情況,可以使用如下SQL命令樣本從慢Query日誌查詢是否有修改過索引。
--查詢最近3小時內執行過修改索引的記錄 select * from hologres.hg_query_log where query_start >= now() - interval '3 h' and command_tag in ('CALL') order by query_start desc limit 500;
正在運行Query時間長度較長如何解決?
- 情況一:執行個體有較長時間的寫入。
解決方案:通過監控指標的即時寫入RPS指標查看是否有持續的寫入任務,從而導致出現Query已耗用時間較長的情況。
- 情況二:事務空閑(idle in transaction)。
- 用戶端開啟事務,進行DDL後未進行commit操作,使用如下SQL命令查詢活躍Query狀態,Query的狀態顯示為
idle in trancation
,且已耗用時間較長。 - Query因為等鎖卡住等原因,導致長時間運行中。
解決方案:通過以下樣本SQL查詢出已耗用時間較長的Query,如果是因為
idle in trancation
導致已耗用時間較長,可以用戶端關閉事務或者設定合理的空閑事務逾時時間,詳情請參見修改空閑Query逾時時間。 - 用戶端開啟事務,進行DDL後未進行commit操作,使用如下SQL命令查詢活躍Query狀態,Query的狀態顯示為
- 情況三:SQL運行複雜且有PQE的Query。解決方案:通過以下命令查詢當前正在運行且已耗用時間較長的Query,然後通過執行計畫(explain sql)查看當前有SQL走了PQE引擎(執行計畫中有
External SQL(Postgres)
),導致執行時間較長。--查看已耗用時間較長的query SELECT current_timestamp - query_start as runtime, datname::text, usename, query, pid::text FROM pg_stat_activity WHERE state != 'idle' order by 1 desc; --查看query的執行計畫 explain sql
- 使用Superuser帳號Kill已耗用時間較長的Query。
- 最佳化SQL中走PQE引擎的運算元,詳情請參見最佳化查詢效能。
- 情況四:並發執行DDL導致搶鎖。
並發執行DDL時會鎖表,導致互相搶鎖,從而出現等鎖,導致已耗用時間較長。
解決方案:- 可以通過如下命令查看是否有DDL正在執行中,並Kill掉對應的DDL,釋放鎖。
SELECT datname::text,usename,query,pid::text,state FROM pg_stat_activity WHERE state != 'idle' ;
- 串列執行DDL。
- 可以通過如下命令查看是否有DDL正在執行中,並Kill掉對應的DDL,釋放鎖。
失敗Query如何排查?
失敗Query代表每秒鐘失敗的Query。Query總數量是時間範圍乘以QPS個數,即時間範圍內的面積。不建議依賴QPS來判斷失敗的總數量。可以通過慢Query日誌排查Query總的失敗數量和失敗原因,並根據報錯針對性的解決,詳情請參見慢Query日誌查看與分析。
Worker CPU負載不均如何解決?
- 原因一:存在資料扭曲。
如果資料存在嚴重的傾斜,那麼Worker的負載就會訪問固定的Shard,導致出現CPU負載不均的情況。
解決方案:需要通過以下語句排查資料扭曲。如樣本結果,某個Shard的數值比其他Shard大太多,從而出現資料扭曲。可根據業務情況處理傾斜資料或者設定合適的Distribution Key,詳情請參見最佳化查詢效能。select hg_shard_id,count(1) from <table_name> group by hg_shard_id; --樣本結果:shard 39的count值較大,存在傾斜 hg_shard_id | count -------------+-------- 53 | 29130 65 | 28628 66 | 26970 70 | 28767 77 | 28753 24 | 30310 15 | 29550 39 | 164983
- 原因二:執行個體設定的Shard數和Worker個數不是整倍數關係。
當Table Group中設定的Shard數和執行個體的總Worker數不是整倍數關係時,意味著不同的Worker上分配的Shard數不同,從而導致負載不均。
解決方案:根據執行個體規格,設定合理的Shard數,詳情請參見Table Group與Shard Count操作指南。一般這種情況出現在較大規格(大於256Core)的執行個體上,小規格執行個體可以使用預設Shard數,無需更改。
- 原因三:有Worker Failover後導致Shard分配不均。
當有Worker因為OOM等原因而被終止(Kill)時,為了能快速恢複Worker的查詢,系統會將該Worker對應的Shard,快速遷移至其他Worker。當被Kill的Worker被拉起後,系統會再分配部分Shard給它,從而出現Worker間Shard分配不均的現象。
解決方案:如果執行個體負載較低,可忽略該負載分配不均的問題。如果執行個體負載較高,可以重啟執行個體以重新均勻分配Shard資源。