內容來源:2017 年 11 月 25 日,數說故事平臺架構團隊高級工程師吳文傑在「Elastic Meetup 廣州交流會」進行《Data Warehouse with ElasticSearch in Datastory》演講分享。IT 大咖說(微信id:itdakashuo)做爲獨家視頻合做方,經主辦方和講者審閱受權發佈。node
閱讀字數:3141 | 8分鐘閱讀數據庫
ES最多使用的場景是搜索和日誌分析,然而ES強大的實時索引查詢、全文檢索和聚合能力也能成爲數據倉庫與OLAP場景的強力支持。本次分享將爲你們帶來數說故事如何藉助ES和Hadoop生態在不一樣的數據場景下構建起數據倉庫能力。數組
數說故事主要業務爲數據商業智能分析,涉及業務包括數字營銷、數據分析洞察、消費者鏈接,同時咱們還擁有本身的數據源。性能優化
目前咱們內部有3種主要取數方式,一種是基於HBase的大規模導出,通俗來講就是Scan HBase掃表,通常用來處理須要全表數據作離線處理的需求。第二種是先從ES query出ID,而後再從HBase get數據,這裏ES被當作了HBase的索引層,這種取數方式在咱們的業務中用的最多。之因此不從ES取數,一方面是由對ES負擔壓力比較大,另外一方面是沒法存放較長的字段。第三種與全量數據庫無太多關係,主要涉及業務層面,好比對已有的ES小庫作打標籤或者ETL操做,而後進行轉化寫入另外一個庫,相似數據倉庫中將工做表提取出來,而後轉換寫入另外一個表。微信
基於這些需求咱們但願有一個可以統一三種取數模型的解決方案,這也就是Gaia項目的由來,Gaia其實就是離線取數與基礎分析能力的構建。架構
Gaia須要解決的問題主要有四點。app
一是構建Hive on HBase/ ES/Banyan(對於三種取數模式)的能力,因爲Banyan是基於ES索引,因此它在構建時要作的事情與ES差很少。工具
二是對不一樣存儲的查詢條件優化,在MySQL中使用where條件查詢之因此會很快,是由於MySQL已經幫你創建的索引。對應到NoSQL中其實也是同樣的,若是where條件沒有與索引層創建好關係,select查詢就會觸發全表掃描,形成很大的負擔。oop
三是提供ES特有的查詢支持。性能
四是提供拓展性的SQL表達能力。
在介紹如何構建Hive on ES/Banyan以前,要先講一下StorageHandler,它是Hive對接外部存儲的核心類,主要功能有三個:InputFormat / OutputFormat(如何讀寫)、MetaHook(如何讀寫Hive元數據)、Predicate Pushdown(下推優化、分解條件)。
這三個功能中InputFormat在作兩件事,首先是InputSplit——按片分割,利用preference制定shard作到並行讀取,第二個是RecordReader——內部先scroll一批數據,而後一直調next到當前數據爲空時,scroll新一批數據。
以前提過Banyan和ES的取數方式其實差很少,不一樣之處在於Banyan擴展了本身的StorageHandler和InputFormat。正常狀況下ES scroll到數據後會直接傳給SearchHit,這裏則新增了讀Hbase的過程,接着再生產新數據填充給SearchHit。
StorageHandler的下推優化在數據庫中是一個比較重要的概念,它涉及到了Sargable和謂語下推兩個概念。Sargable的全稱是Search ARGument ABLE,即SQL中可利用數據庫自身索引優點對查詢條件進行執行性能優化。通常來講能夠優化的爲SQL中的WHERE條件,ORDER BY , GROUP BY, HAVING 等有時候可Sargable,固然狀況並不是絕對,主要仍是和實際數據庫的支持有關。謂語下推是在實際數據讀取和SQL實際執行以前預先執行條件語句進行預處理和過濾。
接下來所講的就是下推優化的具體實現。
首先從StorageHandler中獲取到ExprNodeDesc結點樹對象,再基於該對象構建通用的結點樹。這一步是可行的過程,通常能夠直接基於Hive的原生對象實現,可是咱們想要更加定製化的操做以及同時支持HBase和ES不一樣的存儲,因此仍是將它給抽了出來。
第二步是自頂向下查詢可優化的操做符並進行優化,數據存儲的時候已經預先定義好了可優化的操做符。在遇到不可優化的操做符時,會出現兩種狀況。若是邏輯鏈接符是AND則跳過當前節點並繼續優化兄弟節點,若果是OR則放棄優化。
最後一步是將可優化的結點樹轉爲存儲可支持的查詢條件(ES Query、 HBase Filter等)。
(Hive的源碼對象)
在有了構建能力以後,還須要支持ES特有的查詢。之因此要怎麼作,是因爲像es_match、es_matchphrase之類的,若是是在ES的場景下很好實現,可是要用代碼實現不只麻煩並且性能很低。最後咱們通過考慮,決定對他們的支持不作具體實現,只是返return true,只用來作下推查詢。
在有不少小表的狀況下,若是用戶藉助數參建表,每次須要使用create table還要寫入衆多字段。數據和mapping都在的狀況下,還要使用這種方式實在是過於繁瑣。因此咱們給Gaia新增了一個新的特性——ES自動建表,只須要指定es.nodes和es.resource,就能夠讀取mapping以及數據抽樣檢查,最後生成完整的create table語句。它的實現是基於SemanticAnalyzerHook 攔截 ASTNode語法樹,再讀取ES mapping,重寫 `CREATE` 語句。
從業務層面來看Gaia減小了寫代碼的開銷和出錯率,是更友好的篩選取數工具,同時也爲後續的數據分析提供了基礎。對平臺方來講最重要的是有統一管控計算資源以及審計的能力。
數說立方(Cube) 是數說故事自研的基於ES的OLAP產品,可提供非技術人員自由的導入數據、維度透視、統計分析等功能。
ES爲Cube提供了幾點優點。一是即席查詢,能夠實時查詢且靈活度高,只須要索引字段而不用預計算出維度表。二是佔用空間小,因爲使用ES索引代替維度表,因此空間的開銷得以減少。三是全文檢索支持,lucene支持。
這裏先講下使用Es-hadoop過程當中的一些經驗。
建議使用lasted stable的es-hadoop版本,由於舊版本仍是有些隱性BUG,而新版代碼更加清晰,對舊版也有很好的兼容。
使用時注意一些特殊字段(suggest, array,nested等) ,可能會有坑或不兼容等。好比某個舊版本中在識別到suggest後,就不會再去掃描後續字段。
Es-hadoop還支持跨版本ES的讀寫。在ES5的時候es-rest被獨立出來,用來提供客戶端統一接口讀寫不一樣版本ES的能力。
Cube經過Schema識別實現了ES表的自動導入,這裏主要遇到的問題是ES的數組字段不易識別,所以咱們對導入的庫作了抽樣數據而後進行schema調整。
用戶導入的表可能包含衆多字段,這就出現了一個問題,即什麼樣的數據字段能夠成爲維度。對此除了在產品層面提供給用戶配置以外,咱們還但願可以進行自動識別。所以用到了Cardinality查詢,識別字段的基數,而後設定閥值過濾。