記一次es查詢優化
ELK算是現在比較火的一個技術棧了,這段時間接了一個需求,需要在每天億級別的資料中進行查詢,其中包含了聚合等操作,一陣狂碼雖然需求實現了,但是效能比較差,查詢一次可能需要5-6秒的時間,最為有追求的程式設計師,這樣的效率有些不能接受,於是想了一些辦法優化,下面記錄一下優化的過程。
需求背景
需求1:我司預發環境的埋點資料和線上環境的埋點資料在同一個es索引中,每天的資料量在億級別,QA同學在進行埋點測試的時候希望能夠根據某些條件自動的篩選出他想要的預發環境的資料(注意,這裡可以使用kibana去進行查詢,但是由於我司在埋點管理上有一個自己的平臺,所以希望能夠簡化kibana的功能,只通過滑鼠點選一下就查詢出資料,並和文件進行對比產出校準結果 )。
需求2:對於產品和運營同學,希望能夠對某一個他們關心的埋點進行資料查詢。(注意,對於離線資料,我司有一套自己的資料平臺和離線報表系統,可以讓相關同學非常方便的進行檢視,但是對於實時資料,kibana的使用要求比較高,產品運營同學在沒有經過學習的情況下自然很難熟練快捷的使用 )。
常規實現:
其實這兩個需求一點都不難,對於對es查詢語法比較熟悉的同學來說,需求1就是進行幾個terms匹配,需求2細分為pv和uv,pv就是總量,uv則進行id的聚合即可。
經過我的一頓操作之後,需求完成了,但是效能比較差,特別在具體的使用過程中,有下面這種場景:
查詢資料的時候,並非所有的查詢條件都是精確匹配的,對於某些資料,我們需要進行模糊查詢,而某些場景下,模糊查詢的次數很多,並且條件也很多,在面對億級別的資料的時候,會造成效能的影響,特別是查詢次數較多的情況下,會影響整個叢集的效能。
優化
出現了以上的問題之後,我思考了一下解決方案,優化查詢語句應該是治標不治本的操作,因為資料量就是這麼多,查詢條件也比較苛刻,再怎麼優化語句也不會有太好的效果。於是我決定從源頭出發——既然查詢層面解決不了問題,那就是資料收集層面進行分流。
在說具體的優化之前,我先說一下我司在實時資料處理這個技術棧上並沒有使用logstash,而是用了flink。
對於需求1,其實我只要將預發資料和線上資料進行隔離,寫入到不同於線上資料的另一個es索引中就ok了。預發資料一天也就那麼一點,再怎麼模糊查詢都不會影響效能。這種需求用flink非常好實現,具體的大家可以去學習一下UDF任務。
對於需求2,查詢pv沒有問題,就是一個簡單的hits,而es天生對於count查詢就支援的比較好。對於uv的查詢,之前是在查詢的時候通過聚合的方式操作,而現在則是和需求1一樣,通過flink的AggregateFunction在資料流入的時候就進行篩選,對於某一種資料,同一天內同一個id只輸出一次,而在完成處理之後,同樣的新建一個es索引,將資料存入其中即可。
思考
對於上面的這兩個優化,我得出的一個思考就是:
對於量級比較大的資料查詢來說,與其在查詢上做優化,不如在收集資料的時候就進行清洗。