1、問題描述
1.1 基本信息[Basic Information]
- 集羣規模:37+3臺物理機,每臺128G內存;CPU:2*16C;SATA磁盤,2T*12
- hadoop社區版本:**
- 商業版本:FusionInsight_HD_V100R002C30LCN001SPC005
- MetaStore:高斯數據庫(Postgresql)
1.2 問題描述[Problem Description]
- 10月16日,在執行批量任務時,alter table test change column id id int comment ‘my comment’這類語句執行比較慢,該表150多個分區, 執行需要200多s;
- 在10月13日,同樣的操作,只需要10多s。
- 在執行批量任務時,alter table test change column id id int comment ‘my comment’這類語句偶現失敗。
2、問題分析[Problem Analysis]
2.1 Hive表列屬性偶現失敗問題分析
直接在現網重現該問題,並獲取日誌後進行分析:
1.HiveServer在01:45:31接收到Alter table列信息的請求:
2016-10-16 01:45:31,335 | INFO | HiveServer2-Background-Pool: Thread-45308 | Starting command: alter table hw_test2 change column log_id log_id decimal(24,9) comment '日誌號5' | org.apache.hadoop.hive.ql.Driver.execute(Driver.java:1257)
2.HiveServer向10.0.11.11節點的metaStore發起客戶端連接:
2016-10-16 01:45:31,336 | INFO | HiveServer2-Background-Pool: Thread-45308 | Trying to connect to metastore with URI thrift://10.0.11.11:21088 | org.apache.hadoop.hive.metastore.HiveMetaStoreClient.open(HiveMetaStoreClient.java:378)
3.MetaStore審計日誌記錄了本次alter table的請求:
2016-10-16 01:45:31,355 | INFO | pool-6-thread-187 | UserName=hdmp UserIP=10.0.11.11 Time=2016/10/16 01:45:31 Opertaion=alter_table: db=tmp tbl=hw_test2 newtbl=hw_test2
4.由於執行表的alter table操作的同時,會遍歷修改該表下的所有分區的列的元數據信息,因此在分區數比較多的情況下會耗時較長。而當時HiveServer與MetaStore之間的連接超時時間設置成了10分鐘,如果10分鐘還沒有完成一次任務執行,HiveServer會認爲其MetaStore連接超時,並拋出異常,然後進行重連:
2016-10-16 01:55:31,453 | WARN | HiveServer2-Background-Pool: Thread-45308 | MetaStoreClient lost connection. Attempting to reconnect. | org.apache.hadoop.hive.metastore.RetryingMetaStoreClient.invoke(RetryingMetaStoreClient.java:133)
org.apache.thrift.transport.TTransportException: java.net.SocketTimeoutException: Read timed out
at org.apache.thrift.transport.TIOStreamTransport.read(TIOStreamTransport.java:129)
at org.apache.thrift.transport.TTransport.readAll(TTransport.java:84)
5.於是HiveServer向另一個MetaStore 11.12發起了連接:
2016-10-16 01:55:32,481 | INFO | HiveServer2-Background-Pool: Thread-45308 | Trying to connect to metastore with URI thrift://10.0.11.12:21088 | org.apache.hadoop.hive.metastore.HiveMetaStoreClient.open(HiveMetaStoreClient.java:378)
6.連接到11.12後重試alter table的請求:
2016-10-16 01:55:32,527 | INFO | pool-6-thread-2 | UserName=hdmp UserIP=10.0.11.11 Time=2016/10/16 01:55:32 Opertaion=alter_table: db=tmp tbl=hw_test2 newtbl=hw_test2 | org.apache.hadoop.hive.metastore.HiveMetaStore$HMSHandler.logAuditEvent(HiveMetaStore.java:365)
7.第一次連接中,由於請求已經發送到MetaStore服務端,當客戶端超時認爲失敗後斷開,MetaStore服務端對於元數據庫的修改動作仍在繼續運行直到2點08分這個alter table請求執行成功:
2016-10-16 02:08:59,065 | INFO | pool-6-thread-187 | UserName=hdmp UserIP=10.0.11.11 Time=2016/10/16 02:08:59 Opertaion=alter_table result=success details=null | org.apache.hadoop.hive.metastore.HiveMetaStore$HMSHandler.logAuditEvent(HiveMetaStore.java:365)
8.從01:45到02:08之間,第一次發起的請求一直在更新元數據表的信息,MetaStore服務端持有了表的元數據的行鎖,而01:55時,第二次發起了同樣的請求,則需要等待第一次請求持有的鎖釋放。然而第一次的任務一直持續到02:08,因此,第二次請求到達10分鐘超時時間02:05時,仍未獲取到鎖,任務本次請求失敗,向客戶端拋出失敗異常。
2016-10-16 02:05:38,979 | ERROR | pool-6-thread-2 | Database access problem. Killing off this connection and all remaining connections in the connection pool. SQL State = 08006 | com.jolbox.bonecp.ConnectionHandle.markPossiblyBroken(ConnectionHandle.java:388)
2016-10-16 02:05:38,980 | ERROR | pool-6-thread-2 | Update of object "org.apache.hadoop.hive.metastore.model.MStorageDescriptor@24b03fe" using statement "UPDATE SDS SET CD_ID=? WHERE SD_ID=?" failed : org.postgresql.util.PSQLException: An I/O error occured while sending to the backend.
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:374)
對應失敗的審計日誌:
2016-10-16 02:05:38,983 | INFO | pool-6-thread-2 | UserName=hdmp UserIP=10.0.11.11 Time=2016/10/16 02:05:38 Opertaion=alter_table result=failed details=MetaException(message:The transaction for alter partition did not commit successfully.) | org.apache.hadoop.hive.metastore.HiveMetaStore$HMSHandler.logAuditEvent(HiveMetaStore.java:365)
9.進一步分析10分鐘超時的產生原因,從元數據庫獲取到的調試信息中可以看到對應時間的鎖阻塞情況,第二次01:55開始啓動的請求,爲需要更新Hive元數據庫中的SDS表,被第一次的請求鎖住了13分鐘
10.而第一次請求的執行時間慢的原因在於,測試表的分區數量爲1072個,每個請求都需要更新保存列信息的元數據表COLUMNS_V2,而該表會通過外鍵關聯到核心表SDS,SDS表具有大量的外鍵與其他表進行關聯。
11.從關聯關係中可以看出,在修改列信息的時候會聯動更新若干元數據表的記錄,其中包括元數據核心的SDS表。而針對來自CDS表的外鍵CD_ID沒有創建索引,在聯動修改過程中,需要全表掃描SDS表。
12.在當前SDS數據量達到200W以上級別的前提下,一次全表掃描耗時940ms左右,即每個分區的列信息更新操作,達到一秒左右的時間,1000個分區需要花費1000秒以上。
[2016-10-16 17:22:32.367 CST] gaussdb 12750 LOG: duration: 942.519 ms execute <unnamed>: SELECT 'org.apache.hadoop.hive.metastore.model.MStorageDescriptor' AS NUCLEUS_TYPE,A0.INPUT_FORMAT,A0.IS_COMPRESSED,A0.IS_STOREDASSUBDIRECTORIES,A0.LOCATION,A0.NUM_BUCKETS,A0.OUTPUT_FORMAT,A0.SD_ID FROM SDS A0 WHERE A0.CD_ID = $1 LIMIT 1 OFFSET 0
2.2 Hive表列屬性更新慢問題分析
直接在現網重現該問題,並獲取日誌後進行分析:
1.從執行的SQL語句日誌分析, 在修改列信息的時候會聯動更新若干元數據表的記錄,其中包括元數據核心的SDS表。而針對來自CDS表的外鍵CD_ID沒有創建索引,在聯動修改過程中,需要全表掃描SDS表。
2.在當前SDS數據量達到200W以上級別的前提下,一次全表掃描耗時940ms左右,即每個分區的列信息更新操作,達到一秒左右的時間,1000個分區需要花費1000秒以上。
[2016-10-16 17:22:32.367 CST] gaussdb 12750 LOG: duration: 942.519 ms execute <unnamed>: SELECT 'org.apache.hadoop.hive.metastore.model.MStorageDescriptor' AS NUCLEUS_TYPE,A0.INPUT_FORMAT,A0.IS_COMPRESSED,A0.IS_STOREDASSUBDIRECTORIES,A0.LOCATION,A0.NUM_BUCKETS,A0.OUTPUT_FORMAT,A0.SD_ID FROM SDS A0 WHERE A0.CD_ID = $1 LIMIT 1 OFFSET 0
3.我們模擬了數據量在有無索引情況下的性能:
同樣的表,同樣的數據量,在加索引前,是800多ms,跟生產環境一樣, 加了索引之後,就變成0.1ms,性能提升了幾百倍,因此, 性能慢的問題,判斷爲缺少索引導致的。
4.Alter table add comment有3三種不同表現,a是以前沒有comment的,新增comment;b是已經有comment,修改成不同comment,c是已經有comment,修改成相同comment;這三種情況,b因爲要插入sds,查詢sds,因此耗時最長,c因爲hive使用的datanucleaus組件能判斷出沒有發生變化,沒有操作sds表,因此耗時最短
5.針對用戶反饋10.13號只需要10多秒, 而近期增加的分區信息並沒有那麼多, 爲什麼性能下降這麼快的問題, 將生產環境的dbservice備份數據導入測試環境中, 發現相同的表,執行alter操作需要300s左右,而在增加索引後, 變成了7s,性能提升巨大.
3、根本原因[Root Cause]
3.1 Hive表列屬性偶現失敗
本問題主要包括兩個方面:
- HiveServer與MetaStore客戶端連接超時時間未按照集羣規模進行合理配置;
- 對於大數據量頻繁讀元數據表的情形,缺少針對性優化。
3.2 Hive表列屬性更新慢
- 系統建表未建立索引爲可優化點,根據內部測試,建立索引後性能有較大幅度的提升。
- 用戶之前反應比較快,根據生產環境到測試環境的重建,發現執行修改comment,需要相似的時間,用戶反應之前快,可能是上邊分析中修改的comment前後一樣導致的.
4、解決措施[Corrective Action]
4.1 Hive表列屬性偶現失敗
- 臨時解決措施[Workaround]:將HiveServer與MetaStore連接超時時間調長,使之能滿足業務場景需要,恢復業務運行。
- 最終解決措施[Solution]:爲元數據中需要頻繁訪問的表添加索引,提升訪問效率。
4.2 Hive表列屬性更新慢
- 優化措施[Workaround]:針對查詢慢的問題, 建議在系統空閒時對錶增加索引,提升查詢性能