適用於即席查詢(Ad-Hoc)的OLAP引擎

菜鳥嗯菜鳥發表於2023-11-09

OLAP(OnLine Analytical Processing)是一種資料處理技術,OLAP系統通常被用來進行面向業務主題的資料分析,在大資料量情況快速響應複雜查詢以及靈活的進行隨機性探索性分析是OLAP系統的核心能力。


在OLAP系統中常見的資料模型為以下四種結構:

  • 星型表結構(Star Schema)

  • 雪花型表結構(Snowflake Schema)

  • 寬表結構(Wide Table)

  • 資料立方體結構(Cube)


這幾種常見的結構都可以在邏輯上被理解成是多維空間中的多維立方體。

接下來介紹一個在後續的實踐環節中將要用到的資料模型——Andes Online Store,這是一個電商的銷售資料集合,它關聯了六個維度:日期(Date)、商品(Goods)、地區(Region)、支付方式(Payment Methods)、客戶型別(Customer Types)、銷售渠道(Sales Channels),它有兩個度量:銷售額(Sales)和銷售數量(Sales Count)。

對於這個資料模型,不同的人會有不同的分析需求,例如:

  • 分公司負責人重點關注所在地區的銷售資料,公司決策層更關心整體的銷售資料,整體資料是由各個地區的明細資料聚合而得出,不同的人關注的資料粒度不同;

  • 採購負責人會比較關心商品維度上的資料變化,營銷人員關心的是客戶或銷售渠道維度上的資料變化,而財務人員可能會對日期維度上的資料變化更感興趣,不同的人關注的業務角度不同。


即席查詢(Ad Hoc)是使用者根據自己的需求,靈活的選擇查詢條件,OLAP系統根據使用者輸入的查詢條件實時返回查詢結果。OLAP的即席查詢與普通查詢的不同之處就是很難對前者進行預先的最佳化,因為即席查詢所響應的大都是隨機性很強的查詢請求。一個OLAP系統的即席查詢能力越強,其應對不同使用者的隨機性和探索性分析的能力就越強。


是一個適用於即席查詢場景的開源OLAP引擎,它使用C語言開發,支援單機執行和分散式部署。


透過以下特徵來提供對即席查詢場景的支援能力:

  • 實時聚合 — 對任何維度的粗粒度資料進行實時聚合運算,無需進行預計算處理;

  • 記憶體模式 — 資料被載入到記憶體中的彈性索引結構中,一億資料量只需要3G記憶體,32G記憶體便可支援十億級資料的實時分析;

  • 多維模型 — 採用Cube結構作為語義層模型,其完全可以等同於邏輯多維模型,並且更加貼近現實業務;

  • 複雜查詢 — 使用類SQL語言MDX,MDX在語法結構上與SQL非常類似,但提供了比SQL更加強大的應對複雜查詢的能力;

  • 關聯查詢 — 支援跨Cube查詢,這類似於關聯式資料庫中的Join操作,但 跨Cube查詢不會導致效能明顯下降。


下圖是 單機執行時的架構圖。

  1. 磁碟中資料模型的後設資料部分被載入到記憶體中形成概要檔案(Profile),profile用來描述維度資訊;

  2. 度量資料被載入到記憶體中的彈性索引(Elastic Index)中(如果你瞭解Oracle Essbase或IBM Cogons,那麼可以將彈性索引在邏輯上理解為動態的稀疏維索引和密集維資料塊),彈性索引是 實現高效實時聚合的關鍵;

  3. Profile和彈性索引表示了一個Cube的物理儲存結構,它完全等同於MDX語義層的邏輯多維模型;

  4. MDX解析器接收一個MDX查詢請求並將其解析為一個多維查詢抽象語法樹(AST);

  5. 對AST的進一步處理分為邏輯運算(Logical operation)和聚合運算(Aggregate operation)兩部分;

  6. 邏輯運算將透過概要檔案確定此次查詢請求的資料範圍,同時處理函式解析、數學運算、布林操作等一系列與複雜邏輯相關的步驟;

  7. 聚合運算透過邏輯運算所確定的範圍透過彈性索引進行實時彙總運算;

  8. 將查詢結果以多維結果集(通常是一維或二維)的形式返回。


在分散式部署時, 叢集分為負責邏輯運算的master節點和負責聚合運算的worker節點。一個資料集市模型的維度後設資料被載入到master節點中形成概要檔案,度量資料以分片的形式儲存在各個worker節點中,如下圖所示。

接下來進入實踐環節,我們先使用Docker執行一個 服務,然後模擬各種使用者根據自身的需求面向業務模型進行隨機的探索式的資料分析。


在命令列視窗中執行下面的指令,執行一個 服務:

docker run -d -p 8760:8760 --name euclidolap euclidolap/euclidolap:v0.1.7


文章開始部分已經簡單介紹了用於實踐環節的資料模型示例 — Andes Online Store,這裡我們再回顧一下這個demo。

Date、Goods和Region三個維度具有多層級結構,分別如下:

  • Date:Root(預設全部彙總)> Year > Quarter > Month > Day

  • Goods:Root(預設全部彙總)> 商品大類 > 分類 > 具體商品

  • Region:Root(預設全部彙總)> 洲 > 國家


Payment Methods、Customer Types和Sales Channels三個維度是單層級結構,如下:

  • Payment Methods:Root(預設全部彙總)> 支付方式

  • Customer Types:Root(預設全部彙總)> 客戶型別

  • Sales Channels:Root(預設全部彙總)> 銷售渠道


接下來執行一個簡單的查詢,驗證 是否啟動成功。


執行以下命令進入Docker容器:

docker exec -it euclidolap /bin/bash


在容器中執行olap客戶端命令列工具:

./olap-cli


在olap客戶端中執行下面的MDX查詢語句:

select
[Date].[2022].[Q4] on rows,
[Goods].[Foodstuff] on columns
from [Andes Online Store];

如果你的螢幕上顯示出了相同的結果表示 執行正常。


後面將透過一系列的隨機查詢來演示 的即席查詢能力。


透過任意維度分析資料

下面的3個MDX語句分別從支付方式、客戶型別和銷售渠道三個維度檢視相應銷售額和銷售數量資料。對於其他沒有被顯式指定的維度, 將自動進行彙總。執行下面三個MDX並獲得查詢結果。


支付方式

select
{[Payment Methods].[Credit card], [Payment Methods].[PayPal]} on rows,
{[Measures].Sales, [Measures].[Sales Count]} on columns
from [Andes Online Store]
where ([Date].[2022].[Q4].[M12]);

客戶型別

select
{[Customer Types].[Bargain hunters], [Customer Types].[New customers]} on rows,
{[Measures].Sales, [Measures].[Sales Count]} on columns
from [Andes Online Store]
where ([Date].[2022].[Q4].[M12].[31], [Goods].[Foodstuff].[Meat]);

銷售渠道

select
{[Sales Channels].[Wholesale], [Sales Channels].[Direct sales]} on rows,
{[Measures].Sales, [Measures].[Sales Count]} on columns
from [Andes Online Store]
where ([Date].[2022].[Q4].[M12].[31], [Goods].[Foodstuff].[Meat]);

透過不同的資料粒度進行分析

下面的3個MDX語句分別從商品維度的具體商品、商品分類和商品大類三個粒度進行查詢。


按具體商品查詢2022年1季度銷售額

select
[Date].[2022].[Q1] on rows,
{[Goods].[Foodstuff].[Drink].[Milk], [Goods].[Foodstuff].[Drink].[Tea]} on columns
from [Andes Online Store];

按商品分類查詢2022年1季度銷售額

select
[Date].[2022].[Q1] on rows,
{[Goods].[Foodstuff].[Drink], [Goods].[Foodstuff].[Meat]} on columns
from [Andes Online Store];

按商品大類查詢2022整年的銷售額

select
[Date].[2022] on rows,
{[Goods].[Foodstuff], [Goods].[Clothing]} on columns
from [Andes Online Store];

可以在查詢時將任何維度放置在任何位置

下面這條MDX語句返回的結果是日期與商品維度的交叉透視表,日期與商品被分別放置在列和行上:

select
{[Date].[2021], [Date].[2022]} on rows,
{[Goods].[Foodstuff], [Goods].[Clothing]} on columns
from [Andes Online Store];

稍微修改一下上面的MDX就可以將日期與商品維度的位置互換:

select
{[Date].[2021], [Date].[2022]} on columns,
{[Goods].[Foodstuff], [Goods].[Clothing]} on rows
from [Andes Online Store];

可以對維度進行交叉組合

下面這個MDX語句查詢了各種客戶型別與支付方式對應的銷售資料,客戶型別和支付方式維度被同時放置在行位置並進行交叉組合。

select
Crossjoin(
    {[Customer Types].[Bargain hunters], [Customer Types].[New customers]},
    {[Payment Methods].[Credit card], [Payment Methods].[PayPal]}
) on rows,
[Measures].Members on columns
from [Andes Online Store]
where ([Date].[2022].[Q4].[M12]);

數學運算

下面的MDX定義了一個新的度量Formula_Measure,它的值是對銷售數量度量進行數學運算而得出的:

with 
    member [Measures].[Formula_Measure] 
        as (([Measures].Sales + 1000) / 20 - 33000) * 0.01
select
[Date].[2022].[Q1] on rows,
{[Measures].Sales, [Measures].[Formula_Measure]} on columns
from [Andes Online Store];

跨業務模型分析

下面這個MDX透過LookupCube函式將兩個Cube關聯起來進行分析,這類似於關聯式資料庫中的Join操作,但與Join操作不同之處在於 的跨模型分析不會造成查詢效能的顯著下降。

with 
    member [Measures].other_sales as LookupCube("Sahara Online Store", [Measures].Sales)
select
[Date].[2022].[Q1] on rows,
{[Measures].Sales, [Measures].[other_sales]} on columns
from [Andes Online Store];

函式

下面3個MDX查詢分別使用了成員函式(Member Function)、集合函式(Set Function)和數值函式(Numeric Function)。


使用Parent函式查詢澳大利亞所在洲的2022年的銷售資料:

select
[Region].[Oceania].[Australia].Parent() on rows,
([Date].[2022], [Measures].Sales) on columns
from [Andes Online Store];

使用Children函式查詢球類商品分類下的所有具體商品的銷售資料:

select
Children([Goods].[Motion].[Ball]) on rows,
[Measures].Members on columns
from [Andes Online Store];

使用Avg函式查詢2022年各個季度銷售額的平均值:

with member [Measures].AVG_SALES
    as Avg(Date.currentMember().Children(), [Measures].Sales)
select
Date.[2022] on rows,
[Measures].AVG_SALES on columns
from [Andes Online Store];

邏輯運算

下面的MDX使用了邏輯函式——IsLeaf,當商品維度成員為明細成員時顯示其對應的銷售額資料,對於非明細成員則顯示一個自定義字串。

with member [Measures].mix_num_str
    as Iif(IsLeaf(CurrentMember(Date)), [Measures].Sales, "NO LEAF MEMBER")
select
{Date.[2022], Date.[2022].Q1.M1.[10]} on rows,
[Measures].mix_num_str on columns
from [Andes Online Store];

計算公式維度成員

下面的MDX使用了一個自定義的度量維度成員——Proportion,它的值是透過當前商品維度成員的值與其父級成員的值動態計算得出,可以使用它來檢視各種具體商品佔其所屬商品分類的百分比。

with member [Measures].Proportion 
    as (Goods.CurrentMember, [Measures].Sales) / (Goods.CurrentMember.Parent, [Measures].Sales)
select
[Goods].[Foodstuff].[Fruits].Children() on rows,
[Measures].Proportion on columns
from [Andes Online Store];

自定義集合

下面的MDX在定義查詢條件之前設定了兩個自定義集合——東亞國家和北美國家,這樣在查詢條件中就可以直接使用自定義集合的名稱。

with
    set [East Asian countries] as {[Region].[Asia].[China], [Region].[Asia].[Japan], [Region].[Asia].[India]}
    set [North American countries] as {[Region].[North America].[Canada], [Region].[North America].[United States of America]}
select
Union([East Asian countries], [North American countries]) on rows,
[Measures].Sales on columns
from [Andes Online Store];

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31559044/viewspace-2993651/,如需轉載,請註明出處,否則將追究法律責任。

相關文章