1. 程式人生 > >資料產品通用複合指標查詢計算的實踐

資料產品通用複合指標查詢計算的實踐

本文由作者王改革授權網易雲社群釋出。



一、背景和實現目標

在開發嚴選資料產品(大麥商品資料運營平臺和移動資料工作臺VIPAPP)的時候,最多的業務場景就是對實時和離線資料模型中查詢、處理、統一資料結構返回給前端。所以在開發的同時也一直在思考如何將這些相似的資料處理流程統一起來,更關注資料指標本身。

開發中經常遇到的幾個問題是:


  1. 資料查詢連線管理分散 

  2. 模型查詢結果快取分散 

  3. 對於模型資料查詢結果缺少統一的資料變換模組支援,每日產出的實時資料指標以及離線資料指標經過後端邏輯做介面返回的時候,會有大量的get、set操作,如果同時需要計算指標同比、環比、佔比、對比值等複合指標時,就會充斥大量的重複髒程式碼。

  4. 依賴的資料服務對儲存在MySQL、GP、Kylin、HBase等儲存引擎的資料模型暫時沒有多模型的連線支援。


所以針對以上問題,我們希望能夠設計出能夠在資料產品中使用的通用指標查詢計算模組(DPRequestManager),主要實現如下目標:


  1. 管理資料模型查詢,封裝對於 統一查詢服務(DQS)、MySQL等查詢請求,提供查詢連線池。

  2. 提供靈活的資料變換能力

  3. 能夠通過配置對相應指標(包括指標值、環比、佔比、同比等)自動計算,減少過多的冗餘程式碼。

  4. 支援資料物件對映,減少頻繁的取值和賦值操作

  5. 支援查詢級別的快取(可以根據系統需求自定義快取時間、可以設定快取條件),減少對依賴服務的查詢壓力。


二、通用指標查詢計算模組(DPRequestManager)組織結構

  1. 紅色部分的併發查詢器負責管理資料產品與底層資料查詢儲存引擎的連線,統一管理各種資料查詢。DPRequestManager會作為資料產品模型查詢的統一入口,封裝底層資料模型儲存引擎,為資料查詢提供執行緒池服務。同時此部分還提供模型退化的能力。

  2. 統一快取模組負責對資料查詢做條件快取,對於每日資料未產出或者其他情況可以對查詢結果約定一些必要條件來決定是否快取查詢結果(快取級別為請求級別)。

  3. 橙色部分的資料變換模組可以對DQS獲取的多表資料進行靈活資料變換

  4. 配置模組可以對資料關係對映以及相應的複合指標計算做相應配置,統一生成結果,減少冗餘程式碼


三、資料變換模組支援操作


對於從模型儲存引擎查詢結果處理成List<Map<String, Object>>結構的,並提供提供以下資料變換操作。

命名規則:模組內部將使用資料dataKey存放查詢處理結果,dateKey對應的list結果可以類比excel行列表,其中的列名對應Map結構的key值。

現在主要提供如下資料操作:

1. compose(多個查詢集合進行組合,做記憶體連線使用,對於多個數據中存在同名列的情況,可選擇按照FIFO進行是否覆蓋) compose({"group_id", "group_name"}, "result_A", "resultB")

2. rename(將資料某一列列名重新命名)group(基於元資料行進行分組) rename ("dk", {"sale_amount_day", "sale_qty_day"}, {"sale_amount, sale_qty"})

3. group(基於資料行進行分組) group(row -> new StringJoiner("_").add(row.get("week").add(row.get("group_id")))

4. aggregation(基於資料行進行分組, 然後對度量指標欄位進行聚合) aggregation({"week", "group_id", "group_name"}, {sum("sale_amount"), sum("sale_qty")})

5. shape(資料變形,將多列資料變成寬表資料,平坦化透視表結構)

6. intersection(多個數據集合取交集)

7. top(根據有序度量取top集合)


四、指標計算配置以及物件關係對映


這個地方主要解決兩個問題:

  1. 模型資料查詢結果到資料物件的對映,減少頻繁的取值和賦值,現在通用的ORM框架都能解決這個問題,DPRequestManager為了配合複合指標計算通過反射來實現資料物件對映部分。

  2. 對映過程中的指標計算(指標表達式計算、環比、同比、佔比等複合指標的計算)


DPRequestManager主要是通過兩個配置來配合解決複合指標計算的問題。

第一個配置主要是定義資料物件對映的資料篩選規則(目標資料集合、環比資料集合、佔比資料集合等)

{
    "clazz": StockDTO.class,
    "useDate": "2018-12-07",    // 指定目標值日期
    "hbDate": "2018-12-06",     // 指定環比日期
    "hbKey": "group_id",        // 計算環比使用
    "filterKey": "",            // 過濾器
    "filterValue": ""
}

第二個配置是資料物件DTO的配置(通過註解對複合指標計算進行配置定義)

DTO配置主要使用了三個註解,@FromDO,@FunctionDO,@IgnoreAssign 

@From 定義簡單按key取值

@FunctionDO定義複合指標計算規則(hb,tb,zb,avg,sum等)

@IgnoreAssign 物件對映是欄位忽略

同時支援定義的複合指標物件的指標計算賦值。

@Datapublic class StockSingleVO extends BaseVO {    // 簡單取值,預設駝峰轉下劃線取欄位group_id
    private Long groupId;    @FromDO("'商品組:'+group_name")    private String groupName;    // 簡單取值,直接在庫量
    @FromDO("stock_cnt_zhuzhan_1d")    private Number stockCnt;    // 環比,對在庫量欄位計算環比
    @FromDO("stock_cnt_zhuzhan_1d")    @FunctionDO(types = FunctionTypeEnum.HB)    private Number stockCntHB;    // 簡單取值,計算在庫+在途量
    @FromDO(value = "stock_cnt_zhuzhan_1d+onway_cnt_zhuzhan_1d")    private Number stockAndOnwayCnt;    // 環比計算,計算在庫+在途的環比
    @FromDO(value = "stock_cnt_zhuzhan_1d+onway_cnt_zhuzhan_1d")    @FunctionDO(types = FunctionTypeEnum.HB)    private Number stockAndOnwayCntHB;    // 佔比計算
    @FromDO(value = "stock_cnt_zhuzhan_1d+onway_cnt_zhuzhan_1d")    @FunctionDO(types = FunctionTypeEnum.ZB)    private Number stockAndOnwayCntZB;
}

資料過濾規則配置和資料物件中定義的複合指標計算配置一起支援資料物件對映,這樣可以減少大量重複賦值取值以及手動計算複合指標的工作。同時配合使用資料變換模組和資料物件對映能夠釋放更大的靈活性,將資料變換模組、資料物件對映、複合指標計算模組解耦。

模組查詢程式碼示例:

/**
  * condition1,condition2為構造的指標查詢條件
  */EngineRequest request1 = new EngineRequest(EngineType.DQS, condition1, EngineResultTypeEnum.LIST); // 構造查詢請求1EngineRequest request2 = new EngineRequest(EngineType.DQS, condition2, EngineResultTypeEnum.LIST); // 構造查詢請求2// 構造配置1(資料過濾配置 -> 配置目標日期、環比日期、計算環比目標分組key)EngineConvertConfig config = new EngineConvertConfig<>(StockSingleVO.class, "2018-12-07", "group_id", null, null);
config.setHbDate("2018-12-06");
Listlist = requestEngineManager.initThreadLocal()
        .addRequest(dk1, request1)
        .addRequest(dk2, request2)
        .execute()
        .compose(true, Arrays.asList("date_id", "group_id"), dk_new, dk1, dk2)  // 請求結果連線
        .converToList(dk_new, config); // 資料物件對映// 前端資料結構組裝SmartQueryResult result = BaseVO.assembleResult(list, StockSingleVO.class);


五、總結


資料產品中很多通用的部分可以抽出來作為單獨模組或者服務。文中介紹的複合指標查詢模組已經在大麥商品資料運營平臺中實踐,它把資料產品指標查詢、計算以及物件對映等公共部分提取出來,有效的提高開發效率並能夠降低開發成本。



相關文章:
【推薦】 git submodule