本文為您介紹Hologres監控指標相關的常見問題。
連接數過多時如何查看有哪些連接以及Kill連接?
連接數包括實例中總的SQL連接數,包括Active、Idle狀態的JDBC/PSQL等連接。實例的連接數通常與實例的規格有關,如果您發現連接數過多,甚至出現超出實例最大連接數的情況,或者遇到如下報錯:
產生
FATAL: sorry, too many clients already connection limit exceeded for superusers
報錯。產生
FATAL: remaining connection slots are reserved for non-replication superuser connections
報錯。
說明實例連接數已達上限,通過HoloWeb或者SQL的方式查看當前的連接情況,詳情請參見連接數管理。可以使用Superuser賬號對不符合預期或者Idle的連接進行Kill操作。
查詢延遲過高時如何解決?
常見的延遲過高有以下幾種原因,可以先通過慢Query日志查找對應的慢SQL并根據如下的情況進行解決,詳情請參見慢Query日志查看與分析。
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%左右都屬于正常現象。
一些情況下,會使得內存使用率持續升高,甚至接近80%。主要原因如下:
表越來越多,數據總量越來越大,以至于數據規模遠大于當前計算規格。由于內存使用率和元數據、索引量存在正相關關系,因此,表的數量越多,數據量越大,索引越多,都會導致內存使用率升高。
索引不合理,例如表的列特別多,TEXT列居多,設置了過多的Bitmap或Dictionary索引。此情況可以考慮去掉一些Bitmap或者Dictionary索引,詳情請參見ALTER TABLE。
但是當內存使用率穩定增長,長期接近80%時,通常意味著內存資源可能成為了系統的瓶頸,可能會影響實例的穩定性和或性能。穩定性影響體現在當元數據等過大,超額占據了正常Query可用的內存空間時,在查詢過程中,可能會偶發SERVER_INTERNAL_ERROR
、ERPC_ERROR_CONNECTION_CLOSED
、Total memory used by all existing queries exceeded memory limitation
等報錯。性能影響體現在當元數據等過大,超額占據了正常Query本來能夠使用的緩存空間,從而緩存命中會減少,Query延遲會增加。
因此當內存長期接近80%時,有如下幾個操作建議。
刪除不再查詢的數據,以釋放元數據等占用的內存。
設置合理的索引,若是業務場景用不上的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%如何解決?
當Hologres實例CPU使用率長期接近100%時(例如CPU使用率連續3小時滿載100%,或者連續12小時達到90%以上等),說明實例負載非常高,這通常意味著CPU資源成為了系統的瓶頸,需要分析具體的業務場景和查詢,以判斷原因。可以從以下幾方面進行排查。
排查一: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上漲,存在消耗CPU較高的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時長較長如何解決?
監控指標正在運行Query持續時長中有長時間運行的Query,例如運行時長大于1小時。當出現有長時間運行的Query時,可以先通過活躍Query頁面查看正在運行的Query,詳情請參見Query管理。正在運行Query時長較長,通常有以下幾種情況,可以根據實際情況進行排查。
情況一:實例有較長時間的寫入。
解決方法:通過監控指標的實時寫入RPS指標查看是否有持續的寫入任務,從而導致出現Query運行時間較長的情況。
情況二:事務空閑(idle in transaction)。
客戶端打開事務,進行DDL后未進行commit操作,使用如下SQL命令查詢活躍Query狀態,Query的狀態顯示為
idle in transaction
,且運行時間較長。--查看運行時間較長的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因為等鎖卡住等原因,導致長時間運行中。
解決方法:通過以下示例SQL查詢出運行時間較長的Query,如果是因為
idle in transaction
導致運行時間較長,可以客戶端關閉事務或者設置合理的空閑事務超時時間,詳情請參見修改空閑Query超時時間。--查看運行時間較長的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; --superuser取消query執行 select pg_cancel_backend(<pid>);
情況三: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。
失敗Query如何排查?
失敗Query代表每秒鐘失敗的Query。Query總數量是時間范圍乘以QPS個數,即時間范圍內的面積。不建議依賴QPS來判斷失敗的總數量。可以通過慢Query日志排查Query總的失敗數量和失敗原因,并根據報錯針對性地解決,詳情請參見慢Query日志查看與分析。
Worker CPU負載不均如何解決?
在Hologres中數據分片(Shard)決定了數據的分布情況,一個Worker在計算時可能會訪問一個或者多個Shard的數據。同一個實例中,一個Shard同一時間只能被一個Worker訪問,不能同時被多個Worker訪問。如果實例中每個Worker訪問的Shard總數不同,那么就有可能出現Worker資源負載不均的情況,主要原因如下:
原因一:存在數據傾斜。
如果數據存在嚴重的傾斜,那么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資源。