現在接觸的項目是公司的路由中台,每天的數據量是億級別的,同時要記錄每一次請求的詳細數據
開始的時候這些記錄數據是存放到elasticsearch與DB2數據庫中各自保存
當需要查詢某個路由信息的詳情時從ES中獲取,速度非常快,當想獲取統計報表的時候從DB2中統計,本來是相安無事的,ES速度快,DB2是關系型數據庫,易於統計分析
但是因為公司要放棄DB2數據庫,所以做統計分析的SQL語句也就沒用了,需要從ES中獲取數據並統計分析
這個時候問題就出現了,較為復雜的SQL語句如何轉變為DSL語句
如何分組?如何關聯?如何子查詢
關於基本SQL如何轉變為DSL語句,大家可以參考這個網站http://www.atotoa.com/,同時還有一些開源框架,這里我沒有使用,公司這邊純內網開發,找不到那種東西就沒用,java端使用的是highlevelclient
目前這些轉變中已經做到了分組和聚合的對應,但是其中也有一些細節需要拿出來說一說
一:group by和aggs的區別
SQL語句分組查出來的數據仍然是扁平的數據,最終還是能得到一個List<T> ,但是DSL通過Aggs聚合得到的數據是有深度的,一層套一層,如果想獲取到SQL那種數據結構,理論上來說聚幾次就需要幾層循環一層層的取.
在公司項目改造中,為了取出數據使用了7層循環去取數據
二:也許有的sql還不止7層,使用7層妖塔似乎有點滲人,其他方法有沒有呢
確實可以將聚合拆分,可以每次aggs一次,但是在拿到這些數據時,需要對聚合7次獲取的數據設計一個算法,通過這種方式獲取到數據有問題,最終放棄了(其實這是一個很好的思路,7次聚合帶來的壓力如果分成7個單一聚合,ES服務會非常安全)
三:聚合7次帶來的服務器壓力
公司每日的數據都存入一個新的index,測試庫2000W數據 將近60G 大小,而生產庫每天億級數據,這么大量的數據進行7次聚合,最終會直接讓服務器崩潰
多次測試發現多次聚合都導致了測試ES崩潰,雖然生產服務器更強大,但是這樣肯定不行
四:使用query_match代替聚合
如果要進行兩次聚合,比如下面的語句
實際上也可以使用
將聚合條件轉變為query條件,讓聚合次數降低,單次查詢數量級下降
比如在我的生產庫中有2E跳數據,我使用的query字段有1000個值,那么每次聚合的數據就是2E/1000=20W
把一次查詢ES 2E的數據量變為查詢1000次ES每次查20W的數據量
java代碼雖然復雜了點,但是完全值得