OLAP引擎爲存儲和計算二合一的引擎,自身內部涵蓋了對數據的管理以及提供查詢能力。底層數據徹底規劃在引擎內部,外部系統不容許直接操做底層數據,而是須要經過暴露出來的接口來讀寫引擎內部數據。java
目前總體來講OLAP功能由兩部分組成:數據管理,查詢引擎。sql
引擎中數據核心概念包括:事實表,維度表,模型表,加速表,其中事實表和維度表統稱爲Dataset表。數據操做包括如下幾點:數據庫
其中事實表和維度有如下設計關注點:json
- 事實表和維度表構造起整個OLAP引擎內部的星型結構,能夠經過接口建立一個新的事實表或者維度表;對於事實表,也能夠在建立模型自動建立。
- OLAP引擎內部能夠根據事實表,維度表,模型表建立過程當中所提供的信息,動態的感知出事實表的時間維度、多值維度、外鍵維度、普通維度、去重統計維度以及度量,也能夠感知出維度表中的外鍵維度、普通維度。
- 事實表和維度表的存儲方式能夠根據上面感知到的信息來進行自我規劃,對上層應用來講徹底隱藏。
其中維度表有如下設計關注點:後端
- 每一個維度表都有version版本屬性,即系統中會存在多個版本的維度數據,默認會保存最新N個版本。後續的加速表的每一個批次的數據都是和相應版本的維度表關聯。
- 維度表導入任務與業務維度表生成任務構成導入任務鏈,每次導入都會生成一個新版本的維度表。
- 針對模型自動加速,OLAP引擎只要感知到相應的維度表當天版本已經生成,既能夠開始相應的加速,加速時會選擇當天最新版本的維度表。系統當天不會自動對已經加速的數據由於維度變動而自動更新,須要手動發起加速表的重構操做。
其中事實表有如下設計關注點:api
- 事實表導入任務與業務事實表生成任務構成導入任務鏈。上游業務事實表任務結束之後,會調起個人事實表導入任務,並傳遞上游執行任務所屬於的batch時間。
- 事實表補數操做是OLAP對外提供單次服務接口。OLAP引擎會對請求時間進行拆分,轉化爲多個批次的事實表補數任務,並分發給IDE去執行。
對於一個事實表補數操做,與該事件表的數據加速任務是互斥的,即會對相應的bacth加上讀寫鎖,只有拿到寫鎖,才能夠進行補數操做,不然會一直等待當前批次關聯的加速任務完成。事實表補數結束之後,會對已經完成的加速表進行數據重構操做。
其中模型表有如下設計關注點:架構
- 模型表爲一個視圖表,對外提供表的Create、Delete操做,Delete操做對外接口只會刪除模型相關的meta信息,可是後端須要同時刪除該模型相關聯的加速表的數據。
- OLAP引擎須要根據模型表join關係,肯定模型所歸屬的事實表和維度表,構建起整個數據導入以及加速任務鏈。
其中加速表有如下設計關注點:負載均衡
- 加速表是模型的物化表。對於百川來講,默認會進行Druid和Carbondata兩級物化。
- 對於默認應用場景,OLAP引擎會選擇Druid進行指標的查詢;只有在SQL中強制指定使用Carbondata進行查詢的時候,纔會使用Carbondata進行查詢。
- 在維度表變動之後,能夠經過OLAP引擎接口,一致性重寫相應維度表關聯的加速表,默認狀況下,加速表都會使用當前最新可用的維度表進行加速。
- 加速表的每個批次的加速都有鎖的存在,在鎖衝突的狀況,不會排隊等待,而是會直接失敗,只有當前拿到鎖的加速任務,才能夠進行相應批次的加速。
OLAP引擎調度架構是在Bigquery上進行改進。其中會把服務接口升級爲三種類型:運維
其中同步阻塞接口主要用於請求耗時在3s之內的查詢,其中包括數據管理,集羣管理,以及指標數據查詢;異步非阻塞接口主要服務耗時較差或不可沽的服務接口,其中包括用於數據探測。若是OLAP引擎用於服務百川,與外部數據的交互,包括定時數據遷移,加速及補數,都須要經過IDE任務來實現,OLAP引擎不會直接與外部數據源交互。異步
上圖是OLAP引擎總體架構圖,分爲三個層面:數據存儲層,計算資源層以及OLAP服務層。
Spark指標計算
,異步化任務
都是託管在自身的Yarn資源池內部,同時也只會消費處理自身的Druid、HDFS和HIVE數據。數據入庫
以及模型加速
兩種任務,是由IDE平臺負責調度。它是運行在離線計算集羣上面,它能夠讀寫離線大集羣上的HIVE倉庫以及HDFS存儲,也能夠經過Alluxio Proxy來讀寫OLAP引擎底層的HDFS,可是不能夠直接讀寫OLAP引擎HIVE倉庫,須要經過API層的Query請求進行轉發。OLAP接口服務層主要爲外部提供數據管理以及指標查詢能力。其中定時數據入庫任務、模型加速任務及補數等數據管理操做都是由API層將請求分發給IDE-API層,後續由IDE調度層負責任務的調度和定時執行。OLAP引擎提供的指標計算以及異步化任務都是在OLAP引擎自身調度層的調度下,完成任務執行,其中調度層也負責整個計算的請求路由以及集羣管理。
- 獲取模型關聯的事實表以及維度表,並判斷在當前集羣中是否已經存在;若是相關的維度表不存在,直接報錯;
1.1 若是事實表不存在。
1.1.1 請求離線計算集羣ThritServer,將事實表的scheme克隆到OLAP引擎中,期間會使用Parquet進行存儲。
1.1.2 請求IDE,構建一個事實表遷移任務;
1.1.3 請求IDE,手動補數最近1天(可配置)數據;
1.2 若是事實表已經存在。根據此次提供的事實表相關信息,完善當前咱們對事實表的認識。- 對查詢請求進行SQL翻譯,並在OLAP引擎中構建模型表,在model數據表中存儲模型信息;
- 請求IDE,構建模型的定時加速任務,並記錄到speed表中。
- 模型建立成功。
- API將請求轉發到調度層,由調度層根據當先後端負載狀況,返回一個可用worker。
- API層直接請求worker進行查詢執行。worker首先將SQL按照
;
進行切分,若是爲普通的set語句
,DDL語句
,即當即執行;若是爲select語句
,worker對SQL進行解析和校驗,其中校驗點包括:
2.1 是否爲衍生指標查詢?衍生計算邏輯是否支持?
2.2 內部查詢是否爲UNION子查詢?並校驗每個子查詢模型是否存在?
2.3 校驗子查詢是否有主時間維度?並校驗涉及到的分片數是否在閾值以內?
2.4 校驗全部分片是否都已加速?
2.5 校驗聚合指標是否爲sum,count,max,min,count distincts五種?
2.6 校驗count distinct的維度是否在模型配置列表中?
2.7 校驗case when語句是否爲單case when語句,而且else被置爲0或者null?- 若是
bigquery.accurate.count_distinct=true
,只能選擇carbondata進行加速,不然默認都選擇druid進行加速。- 在carbondata或者druid上完成SQL查詢,並直接返回查詢結果給API層。
注意:處理到第一條select語句後,將會結束後面SQL的執行。
注意:關於多時間維度:
對於一個模型,它必需要有一個分區時間字段和1個或多個業務時間字段,其中分區時間字段爲粗粒度,而業務時間字段爲細粒度。
在模型加速過程當中,若是一個模型只有一個1個業務時間字段,即便用業務時間字段做爲主時間維度;不然將使用分區時間字段做爲主時間字段進行加速。
在指標查詢過程當中,必須帶上
主時間
維度過濾條件。對於單時間模型,查詢的時候必須帶上相應的業務時間過濾條件;對於多時間模型,查詢的時候就必須帶上分區時間過濾條件。 好比多時間模型,分區時間爲a,兩個業務時間b,c,查詢的時候必須在維度上a作時間過濾,不然會全表掃描; 好比單時間模型,分區時間爲a,業務時間爲b,查詢必須是基於業務時間b來構建過濾條件。
http://www.xiaoyaoji.cn/dashboard/#!/share/AmjDtLow2
如上所述,OLAP引擎由三組存儲組成:MySQL核心Meta存儲、HBase異步化任務狀態KV存儲、以及Hive/HDFS數據存儲。其中核心Meta存儲採用MySQL進行存儲,包括Dataset
,Model
,speedup
,Partition
四個表;HBase僅僅用來存儲數據探測等異步化任務相關信息;事實表、維度表、加速表等數據存儲在Hive/HDFS中。
dataset
表存儲了系統中全部的事實表和維度表,經過type
字段進行標識,可選{"0":"事實表","1":"維度表"}
;
在建立事實、維度表時,須要指定表所關聯的上游任務pre_ide_job_id
和granularity
,OLAP引擎在IDE中建立按期遷移數據任務,任務流ID和任務ID分別爲ide_flow_id、ide_job_id
;
meta
字段是OLAP對該表的認知,隨着上層模型創建,認知也會逐漸豐富起來。
CREATE TABLE `bigquery_dataset` (
`id` INTEGER NULL AUTO_INCREMENT DEFAULT NULL,
`database` VARCHAR(128) NULL DEFAULT NULL,
`tablename` VARCHAR(128) NULL DEFAULT NULL,
`type` TINYINT NULL DEFAULT NULL,
`pre_ide_job_id` VARCHAR(128) NULL DEFAULT NULL,
`granularity` TINYINT NULL DEFAULT NULL,
`ide_flow_id` VARCHAR(128) NULL DEFAULT NULL,
`ide_job_id` VARCHAR(128) NULL DEFAULT NULL,
`meta` MEDIUMTEXT NULL DEFAULT NULL COMMENT 'json',
PRIMARY KEY (`id`),
UNIQUE KEY `dataset_unique_key` (`database`,`tablename`),
UNIQUE KEY `pre_ide_job_id_unique_key` (`pre_ide_job_id`),
UNIQUE KEY `ide_job_id_unique_key` (`ide_flow_id`,`ide_job_id`),
);
其中meta字段Json結果以下所示:
{
"dimensions":[
{
"dimension":"維度名稱",
"type": "維度類型",
"cardinality":"維度基數",
"is_time":"是否爲時間字段",
"time_format":"時間字段格式",
"is_partition":"是否爲分區字段",
"is_key":"是否爲維度外鍵",
"is_multivalue":"是否爲多值列",
},
],
"measures": [
{
"measure":"度量名稱",
"type":"度量類型",
},
],
}
model
爲存儲業務模型,每一個模型歸屬一個database
;granularity
爲模型時間間隔,它與所依賴的事實表時間間隔一致;ttl
單位天,表示模型關注的時間,超過這個時間的物化數據,將會從系統中移除。meta
存儲詳細描述信息。
CREATE TABLE `bigquery_model` (
`id` INTEGER NULL AUTO_INCREMENT DEFAULT NULL,
`name` VARCHAR(256) NULL DEFAULT NULL,
`database` VARCHAR(256) NULL DEFAULT NULL,
`queryGranularity` VARCHAR(64) NULL DEFAULT NULL,
`ttl` INTEGER NULL DEFAULT -1 COMMENT 'model關注時間',
`meta` MEDIUMTEXT NULL DEFAULT NULL COMMENT '存儲模型詳細信息',
PRIMARY KEY (`id`),
UNIQUE KEY `model_unique_key` (`name`,`database`),
);
其中meta格式以下所示:
meta={
"fact":{},
"relations":[],
}
//
fact={
"database":"",
"tablename":"",
"filter":"",
"meta":{
"dimensions":[
{
"name":"",
"dimension":"",
"type":"",
"is_time":"",
"time_format":"",
"is_partition":"",
"is_multivalue":"",
"is_radix":"",
}
],
"measures":[
{
"name":"",
"measure":"",
"type":"",
}
],
}
}
//
relations=[
{
"database":"",
"tablename":"",
"dimensions":[
{
"name":"",
"dimension":"",
"type":"",
"is_multivalue":"",
"is_radix","",
}
],
"join":{
"type":"",
"items":[
{
"dimension":"",
"fact_dimension":"",
},
],
},
"filter":"",
}
]
speedup
爲模型加速表,單個模型能夠有druid
和carbondata
兩種加速類型,經過type
字段進行標識;每一種類型加速根據聚合粒度queryGranularity
,能夠有多個加速寬表,每個加速寬表對應一個IDE實體遷移任務ide_job_id
。
CREATE TABLE `speedup` (
`id` INTEGER NULL AUTO_INCREMENT DEFAULT NULL,
`model` VARCHAR(256) NULL DEFAULT NULL,
`database` VARCHAR(256) NULL DEFAULT NULL,
`type` INTEGER NULL DEFAULT NULL,
`name` INTEGER NULL DEFAULT NULL,
`ide_flow_id` INTEGER NULL DEFAULT NULL,
`ide_job_id` INTEGER NULL DEFAULT NULL,
`queryGranularity` INTEGER NULL DEFAULT NULL,
`scheme` MEDIUMTEXT NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `speedup_unique_key` (`model`,`database`, `type`, `queryGranularity`),
UNIQUE KEY `speedup_name_unique_key` (`name`),
);
partition
數據分區表。不論是dataset
仍是speedup
,都只是存儲表的邏輯信息,實際數據都須要以分區的形式遷移或假設而來(注意:維度表遷移是完整遷移,能夠理解分區爲0到無窮大),每一次遷移或拉寬都對應一條記錄存儲在partition
分區表中。
type
表示分區類型,可選值有dataset
,speedup
,relation_id
爲外鍵,分別關聯dataset.relation_id
和speedup.relation_id
;每個分區都有一個interval
字段,標識該分區所屬於的時間段,參考標準。
interval
記錄能夠有多個版本,經過version
表示;對於speedup
以及dataset.fact
數據,底層數據只會保存一個版本,數據庫中記錄也只有一條(經過updateOrInsert來實現);而對於dataset.dim
數據,底層會保存歷史多個版本,數據庫中記錄條數也會有多條記錄。
若是type=speedup
,versions
字段存儲了它所依賴的各個表的維度信息,格式爲[{"database":"","tablename":"","version":""}]
CREATE TABLE `partition` (
`relation_id` INTEGER NULL DEFAULT NULL,
`type` VARCHAR(128) NULL DEFAULT NULL,
`interval` INTEGER NULL DEFAULT NULL,
`version` VARCHAR(64) NULL DEFAULT NULL,
`status` TINYINT NULL DEFAULT NULL,
`ide_instance_id` INTEGER NULL DEFAULT NULL,
`versions` MEDIUMTEXT NULL DEFAULT NULL,
UNIQUE KEY `partition_unique_key` (`relation_id`,`type`,`interval`, `version`)
);
task
爲HBase表,存儲了Task相關信息,經過type
參數來區分不一樣類型。cf1.content
字段存儲任務的參數信息;cf2.data
字段存儲任務的執行過程當中或者結束之後大Blob信息。
{
"name": "ns_bigdata:bigquery_task"
"cf1": {
"type":"任務類型",
"content":"任務內容",
"user":"",
"create_time":"",
"priority":"",
"timeout":"",
"status":"",
"update_time":"",
"worker:"",
"progress":"",
"schedule_cost:"",
"execute_cost:"",
"fail_desc:"",
"count:"",
},
"cf2": {
"scheme":"查詢結果的scheme",
"data":"查詢結果"
}
}
針對不一樣的Type,content等字段取值也有全部不一樣。
//type=survey/create
content={
"query":"查詢sql語句",
"sample": {
"block_enabled":true,
"record_enabled":true,
"ratio":""
},
}
process=[
{
"sub_query":"",
"sub_query_status":"",
"sub_query_detail":[
"job_id":"",
"job_status":"",
"job_detail":[
{
"stage_id":"",
"stage_status":"",
"total_tasks":"",
"succeeded_tasks":"",
"failed_tasks":"",
"start_time":"",
"end_time":"",
}
]
],
}
]
//type=migrate/delete
content={
"database":"",
"tablename":"",
}
//type=migrate/redo
content={
"relations":[
{
"database":"",
"tablename":"",
"interval":"",
},
],
"migrate":true,
"speedup":true
}
process={
"migrate":[
{
"database":"",
"tablename":"",
"interval":"",
"ide_instance_id":"",
}
],
"speedup":[
{
"model":"",
"interval":"",
"type":"",
"task_id":"",
}
],
}
//type=model/delete
content={
"model":""
}
//type=speedup/create
content={
"model":"",
"interval":"",
"type":"",
"queryGranularity":""
}
progress=[
{
"interval":"",
"queryGranularity":"",
"ide_instance_id":"",
}
]
OLAP引擎數據搬遷和加速操做都是以任務的形式運行在IDE平臺上,調度方式包括定時調度和手動補數兩種類型。對於定時調度,OLAP引擎負責IDE任務及任務流的建立,IDE負責定時執行任務;對於手動補數,OLAP引擎負責對請求進行拆分爲多個IDE補數任務,由IDE進行調度排隊及執行。
migrate
和speedup
爲兩個java二進制程序,資源託管在IDE平臺中。IDE平臺支持建立任務/api/bigquery/ide/flow/create
時,經過指定該資源名稱或者ID來使用它們,同時也支持對任務資源進行升級/api/bigquery/ide/task/upgrade
。
migrate
和speedup
使用方式以下:
migrate database tablename [batch]
speedup model type queryGranularity [batch]
//參數描述:
//database、tablename和speedup、model、type是在建立IDE任務時指定的任務自定義參數param。在定時調度以及補數時,IDE負責將其做爲參數傳遞的程序。
//batch爲IDE內部調度過程當中,傳遞給程序的參數,程序內部還須要經過batch獲取到當前執行的ide_instance_id。
//若是爲補數任務,batch支持經過接口傳遞給IDE
關於batch的概念:
在OLAP引擎中,數據是按照interval
進行表示,可是在IDE任務中,是經過batch
來進行標識,它們關係以下:
batch=interval_end_time
即batch
爲interval
結束時間interval=batch-max(granularity,queryGranularity)/batch
。
對於migrate
任務,queryGranularity=0
;
對於speedup
任務,queryGranularity=granularity * n
,默認n=1
。
migrate
任務流程以下:
- 校驗待遷移源數據進行校驗:
dataset
數據庫中有該事實表或者維度表記錄?源Hive分區數據是否存在,並預計算分區內數據條目數。- 嘗試獲取該表的遷移分區的
寫鎖
。處於寫鎖
狀態的分區,不容許並行寫,也不容許被加速任務讀取。鎖的值須要記錄當前鎖持有者的相關信息,包括當前鎖持有者的機器,進程號,服務類型。若是當前有另一個服務佔用寫鎖
,那該任務將會直接失敗;若是由於當前有讀鎖
,那麼將會持續等待下去,最長等待時間爲30分鐘(每次sleep 1分鐘,重試獲取30次)。- 在OLAP引擎
Partition表
中記錄該次遷移的描述信息,狀態標記爲running
。其中若是爲維度表,在Partition中新增一條記錄;若是爲事實表,直接在原有記錄上進行修改。- 若是爲事實表,須要刪除原始實時表底層的HIVE分區以及底層HDFS數據。
- 開始HDFS數據遷移,而且對遷移後的數據進行條目數校驗。
- 將HDFS路徑關聯到OLAP引擎Hive Meta中。若是爲事實表,經過
add partition
來將相應的HDFS路徑關聯到表中;若是爲維度表,經過alert table
來修改當前維度表的path路徑。- 遷移結束之後,更新分區表Partition中遷移狀態。
- 釋放
寫鎖
- 收集數據遷移相關metric信息,完成遷移操做。
speedup
任務流程以下:
- 校驗當前
batch
是否爲queryGranularity
結束點,若是不是,選擇跳過。好比queryGranularity=1d
,若是batch爲2017071812
就直接跳過,只處理batch=2017071900
。- 獲取指定
speedup
分區的全局寫鎖
;獲取所依賴的事實表、維度表指定分區的全局讀鎖
- 校驗所依賴的事實表、維度表指定的分區數據是否存在,若是不存在,直接報錯;不然就獲取相應的版本信息。
- 校驗當前拉寬後的scheme是否存在(存儲在
speedup
表的scheme
字段),若是沒有,進入scheme探測邏輯。
4.1 嘗試獲取指定speedup表的scheme探測全局鎖
。
4.2 拿到全局鎖
,進行scheme探測邏輯,生成scheme,並寫到speedup
表中,釋放全局鎖
。
4.3 未拿到全局鎖
,等待1分鐘,再次檢查scheme是否存在,進入2.1步邏輯。
4.4 最長等待時間爲30分鐘。- 在分區表Partition中記錄該次加速的描述信息,狀態標記爲
running
。- 開始加速。
- 遷移結束之後,更新分區表Partition中遷移狀態。
- 經過zk進行事件通知,通知全部的worker有新的加速分區上線。
- 釋放所依賴分區的
全局讀鎖
;釋放加速分區的全局寫鎖
。- 收集數據遷移相關metric信息,完成遷移操做。
針對百川,OLAP引擎提供指標查詢的接口爲同步,而針對數據探測項目,是採用異步接口。請求模塊間流轉以下所示:
異步接口:
- API層響應數據探測任務的建立操做,在HBase中記錄任務相關信息,並返回任務ID給業務端。
- API層將任務轉發給Master層,由Master負責排隊等待,並將請求調度到指定Worker層進行處理。
- 在任務運行過程當中,Master層隨時會響應來自API層的任務Kill請求,Master會與任務運行Worker進行通訊,從而將任務從Worker中殺死。
- 任務計算過程當中,Worker會將任務的中間狀態更新到HBase中,從而能夠被API層查詢並返回給業務端。
- 任務計算完成之後,Worker會在HBase/HDFS中寫入任務狀態和數據。同時通知Master層,任務執行結束。
- API層經過查詢HBase/HDFS記錄信息來獲取任務的執行結果,並返回給業務端。
整個環節中,API層不會和Worker直接進行RPC通訊。
同步接口:
- API層響應百川的指標查詢請求,此時會建立一個任務ID,可是不會在HBase中記錄該Task的任何信息。
- API層請求Master,根據任務相關信息,由Master進行負載均衡,流控等操做,並給出可用的後端Worker,並返回給API層。
- API層同步請求後端Worker,等待Worker完成指標的計算,並返回計算結果給API層。期間Worker不會將狀態、數據落地到HBase和HDFS中。
- Worker計算完成之後,須要通知Master層;
- 在Worker計算過程當中,Master層支持響應Kill操做來殺死指標查詢請求(僅僅用於運維管理)。
在OLAP引擎中,模型或者模型表是虛擬概念,其中不真正包含數據,對模型的查詢,須要經過一個策略轉換爲對模型的加速表的查詢,這個策略即模型數據路由。
加速表是按照interval對模型進行加速,OLAP引擎核心路由也是基於對查詢所依賴的interval分區數據進行路由。OLAP引擎的Worker模塊會實時監聽每一個加速表的interval分區上線以及上線操做,只有一個查詢所關注的全部interval分區都在線,該加速表纔會提供查詢服務。
若是有一個查詢由於查詢指標和維度只能使用carbondata進行查詢,那麼將會路由爲carbondata加速表,不然默認都是使用druid加速。同時,若是指定的加速表有多個queryGranularity,系統須要自動選擇知足查詢的最大的queryGranularity;好比查詢語句是查詢最近1月的聚合指標,那麼優先使用queryGranularity=1月的加速表,而不使用queryGranularity=1天的加速表。
關於interval分區上線或上線:
worker啓動時,會對partition
表進行掃描,對每一個模型的每張加速表,會在內存中構建bitmap,bitmap的大小結果以下:hashmap(
2017年->bitmap(366天*24小時/queryGranularity小時),
2016年-> bitmap(366天*24小時/queryGranularity小時)
)
好比queryGranularity爲1天的加速表,每一年的bitmap大小就爲366;若是爲1小時的加速表,那麼每一年的bitmap大小就爲366*24。
//
worker在運行過程當中,會響應對分區的上線下線操做事件,好比/api/bigquery/datamanager/model/speedup/delete
會向全部Worker通知指定interval的數據操做。
在IDE加速任務完成之後,也會經過事件的方式通知全部Worker有新的Interval能夠提供查詢服務。
select count(度量) from 模型 group by window(小時/天), 維度1,維度2 where 過濾條件
select count(case when 過濾條件 then 度量 else null) from 模型 group by window(小時/天), 維度1,維度2 where 過濾條件
//
select count(distinct 維度) from 模型 group by window(小時/天), 維度1,維度2 where 過濾條件
select count(distinct case when 過濾條件 then 度量 else null) from 模型 group by window(小時/天), 維度1,維度2 where 過濾條件
//
select sum(度量) from 模型 group by window(小時/天),維度1,維度2 where 過濾條件
select sum(case when 過濾條件 then 度量 else null) from 模型 group by window(小時/天),維度1,維度2 where 過濾條件
//
select max(度量) from 模型 group by window(小時/天),維度1,維度2 where 過濾條件
select max(case when 過濾條件 then 度量 else null) from 模型 group by window(小時/天),維度1,維度2 where 過濾條件
//
select min(度量) from 模型 group by window(小時/天),維度1,維度2 where 過濾條件
select min(case when 過濾條件 then 度量 else null) from 模型 group by window(小時/天),維度1,維度2 where 過濾條件
//
select metric組合 from 模型 group by window(小時/天),維度1,維度2 where 過濾條件
//
select 維度,度量 from 模型 where 過濾條件
支持SQL Union
度量值,維度值,過濾條件支持UDF轉換
過濾條件支持多值組合 and or組合
支持order by和limit num
支持子查詢
支持指標結果運算
簡單說:OLAP就是
![](http://static.javashuo.com/static/loading.gif)