您好,登錄后才能下訂單哦!
簡述:
和寫流程對比起來,HBase讀數據是一個更加復雜的操作流程,這主要基于兩個方面的原因:
其一是因為整個HBase存儲引擎基于LSM-Like樹實現,因此一次范圍查詢可能會涉及多個分片、多塊緩存甚至多個數據存儲文件;
其二是因為HBase中更新操作以及刪除操作實現都很簡單,更新操作并沒有更新原有數據,而是使用時間戳屬性實現了多版本。刪除操作也并沒有真正刪除原有數據,只是插入了一條打上”deleted”標簽的數據,而真正的數據刪除發生在系統異步執行Major_Compact的時候。
很顯然,這種實現套路大大簡化了數據更新、刪除流程,但是對于數據讀取來說卻意味著套上了層層枷鎖,讀取過程需要根據版本進行過濾,同時對已經標記刪除的數據也要進行過濾。
1、scan一次,現在內存中找,如果找到了后,就直接返回給客戶端
2、如果沒有找到再在 blockcache hfile memcache 中一行一行進行掃描,掃到100行之后,就返回給客戶端
3、客戶端將這100行數據緩存到內存中并返回給一條給上層業務。
這里是每次都會調用100行數據,客戶端拿到之后,再掃描100條數據,直到數據被全部拿到
上層業務不斷一條一條獲取掃描數據,在數據量大的情況下實際上HBase客戶端會不斷發送next請求到HBase服務器。有的朋友可能會問為什么scan需要設計為多次next請求的模式?個人認為這是基于多個層面的考慮:
1、HBase本身存儲了海量數據,所以很多場景下一次scan請求的數據量都會比較大。如果不限制每次請求的數據集大小,很可能會導致系統帶寬吃緊從而造成整個集群的不穩定。
2、如果不限制每次請求的數據集大小,很多情況下可能會造成客戶端緩存OOM掉。
3、如果不限制每次請求的數據集大小,很可能服務器端掃描大量數據會花費大量時間,客戶端和服務器端的連接就會timeout。
get的批處理操作是安裝目標region進行分組,不同分組的get請求會并發執行讀取。然而scan并沒有這樣實現。
也就是說,scan不是并行操作。
所以從客戶端視角來看整個掃描時間=客戶端處理數據時間+服務器端掃描數據時間,這能不能優化?
小結:
根據上面的分析,scan API的效率很大程度上取決于掃描的數據量。通常建議OLTP業務中少量數據量掃描的scan可以使用scan API,大量數據的掃描使用scan API,掃描性能有時候并不能夠得到有效保證。
引出問題:HBase作為列式存儲,為什么它的scan性能這么低呢,列式存儲不是更有利于scan操作么?Parquet格式也是列式,但它的scan這么優秀,他們的性能差異并不是因為數據組織方式造成的么?kudu也是采用的類LSM數據結構,但是卻能達到parquet的掃描速度(kudu是純列式的),kudu的一個列也會形成很多文件,但是好像并沒影響它的性能
小結:
個人對Kudu不是很懂,不過旁邊有Kudu大神。我的理解是這樣的:
所以說hbase相比parquet,這兩個方面都是scan的劣勢。
參考鏈接:
HBase原理-數據讀取流程解析 http://hbasefly.com/2016/12/21/hbase-getorscan/
HBase最佳實踐 – Scan用法大觀園 http://hbasefly.com/2017/10/29/hbase-scan-3/
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。