DorisDB | 原理剖析和應用實踐篇


1. 數據驅動

數據驅動的新趨勢

對速度和性能要求越來越高: 查詢(亞秒級別返回),快速開發,

傳統的方式進行預計算kylin、clickhouse, 星型模型--寬表模型--預聚合--(聚合度越高就會喪失一些靈活性,業務變更、維度變化就要重新刷新數據)

星型和雪花模型的多表關聯, 高效的即席查詢,預計算;

kylin+hbase做預處理

實時分析druid-聚合模型(對寬表支持度不高)

寬表選用clickhouse(對更新不友好)

Impala+kudu實現更新+多表關聯

ES 全文檢索、倒排索引;

Doris解決不同系統之間的差異;

支持Mysql、ES、Hive的外表;

Doris數據源: kafka、hdfs、file、datax-mysql等數據庫;

spark、flink對doris數據的讀寫;

支持外部表: 小的維度表更新可以放mysql,更新、倒排索引可以放ES(聚合|關聯不太友好),創建hive的外部表等

2. 整體架構 - MPP架構

彈性MPP架構-極簡架構

FE前端節點, 主要負責元數據的管理,查詢的規划調度,解析sql對應的執行計划下發給BE

BE數據的存儲和執行的引擎,這里存儲和計算還是在一起的;

FE分為Leader、 Follower、 Observer

Follower, 參與選主,一個Follower宕機會自動選主, 保證服務的高可用; 可水平擴展, 線性增加只讀的observe節點 以應對高並發的查詢

對外提供mysql兼容協議,像navicat等工具都可以直接連接,客戶的遷移成本比較小; 

 

跟傳統架構的區別:

通過分布式拆分成不同的task在每個節點運行,再在中心節點匯聚;

druid、clickhouse都是類型架構;

離線計算MR是任務的拆分、落盤,會有一定的等待磁盤IO,合適跑特別大的任務;

doris是MPP架構,任務之間分成task、全都在內存中執行和傳輸,所有任務都是流水線,沒有磁盤IO,適用於低延遲亞秒級查詢;

sql查詢進入doris的過程:

MPP架構的使用邏輯

將上邊的sql解析成邏輯執行計划-

A|B兩個表的scan -> Join ->聚合(group by K1 sum(V1) )聚合操作 -> 最后再sort by sum(V1)排序 ;

MPP架構就是可以把邏輯執行計划轉換成物理層面的,

假設有3個節點,會把執行計划分成類似fregment (有節點的組合); scanB掃描B表的數據,通過一個brokercast、dataSink和exchange這樣的節點會把fregment串聯起來,每個fregment中會有不同的計算節點;

比如數據經過廣播跟A表join,之后進行聚合操作;

在doris中一個MPP就是支持兩層的數據聚合,像在Scatter/Gather中每個節點做完聚合操作后最后匯總到一個節點再做一次;

在doris中支持在中間做一次數據的shuffle,shuffle完成之后在上層再做一次聚合,這樣子就不會有大單點的計算瓶頸。再推給上層去做排序。

根據不同的機器每個fregment會拆成instent它執行的子單元,就可以充分發揮MPP的多基多合的能力,根據機器數量和設置的並行度,充分利用資源。

智能CBO查詢優化器

dorisDB跟開源的apache doris有幾個改造點:

在FE這邊的改造:

plan會根據cpu的成本預估,加入更多的統計信息(列的基數、直方圖等等),能夠更准確的預估表的執行計划。

兩個表join時,使用brokercast join還是shuffle join還是其他join的一些方式,左右表過濾出來應該有多少行數等,哪個表作為左右表等位置關系;聚合函數用1層還是2層等等 會有更好的執行調度

在全新的plan下,對復雜的查詢可以提高7-10倍的性能優勢;

 

極速向量化引擎

對BE的改造點:

計算+存儲層,

計算層:  在簡單化查詢上的性能提升,主要是向量化引擎,即把內存結構按照列的方式進行組織;

跟之前按行來處理不一樣的地方是 可以充分利用全新的cpu指令(單指令、多數據流),一條指令可以處理很多的數據。

高效的列式存儲

列式存儲:

  • 支持排序,選擇排序鍵,對數據進行排序二分查找,前綴索引快速找到對應數據。
  • 支持二級索引:bitmap、 bloom filter等來構建二級索引;
  • 延時物化通過讀取時對數據裁剪,過濾條件應用在引擎中降低數據的讀取量;
  • 編碼加速,對數據的估計做一些自適應編碼,轉化成字典編碼,對列讀取的性能提升;
  • 算子智能下推會把復雜查詢推到存儲層, 向量化指令做過濾等。

現代化物化視圖加速


不同場景下預處理 :

kylin的cube,doris中的物化視圖;

圖中要計算每個日期和id的pv個數,可以創建物化視圖, 預習計算好每個date的pv個數,每個id的pv個數,再進行查詢時進可以直接從物化視圖中查詢;

doris的物化視圖跟clickhouse的區別 : 

clickhouse中是直接去查詢它的物化視圖那張表,

doris中是透明的物化視圖, 會有一個智能路由,查詢的時候還是查詢原表它會路由到效果最好的一張物化視圖中。

自動化構建 - 離線異步構建物化視圖;新增的實時更新到物化視圖中;

 

實時構建DWS數據

實時數據分析報表的場景:

flume-kafka-doris(進行實時數據的聚合)-BI工具的展示

Join優化 — colocated Join

 

 

doris多表關聯有一個明顯的優勢 :

原來的建模傾向於寬表,一旦維度的變更就會導致數據的重新刷新,靈活性降低。

doris現場關聯,秒級查詢返回;

除了高效的shuffle join外還會有一個colocate join 降低特別大的兩個表關聯時的數據傳輸量。

shuffle join左右表會根據shuffle key回寫重新排布后再進行關聯,會消耗很多網絡帶寬和時間;

colocate join 在建表時就指定數據的分布方式,相同的數據可以哈希到一個桶中,所有的數據都可以在本地進行關聯操作,最后再在上層做一次數據的聚合,就可以完成高效的數據管理。

極簡運維,彈性伸縮

3. 性能測試

 

 

 

 

 

------------------------doris建表-------------------
CREATE
TABLE `lineorder_flat` ( `lo_orderdate` date NOT NULL COMMENT "", `lo_orderkey` int(11) NOT NULL COMMENT "", `lo_linenumber` tinyint(4) NOT NULL COMMENT "", `lo_custkey` int(11) NOT NULL COMMENT "", … `p_color` varchar(100) NOT NULL COMMENT "", `p_type` varchar(100) NOT NULL COMMENT "", `p_size` tinyint(4) NOT NULL COMMENT "", `p_container` varchar(100) NOT NULL COMMENT "" ) ENGINE=OLAP DUPLICATE KEY(`lo_orderdate`, `lo_orderkey`) COMMENT "OLAP" PARTITION BY RANGE(`lo_orderdate`) (PARTITION p1 VALUES [('0000-01-01'), ('1993-01-01')), PARTITION p2 VALUES [('1993-01-01'), ('1994-01-01')), PARTITION p3 VALUES [('1994-01-01'), ('1995-01-01')), PARTITION p4 VALUES [('1995-01-01'), ('1996-01-01')), PARTITION p5 VALUES [('1996-01-01'), ('1997-01-01')), PARTITION p6 VALUES [('1997-01-01'), ('1998-01-01')), PARTITION p7 VALUES [('1998-01-01'), ('1999-01-01'))) DISTRIBUTED BY HASH(`lo_orderkey`) BUCKETS 48 PROPERTIES ( "replication_num" = "1", "in_memory" = "false", "storage_format" = "DEFAULT" ); ------------------------clickhouse建表------------ CREATE TABLE ssb_100g.lineorder_flat( `lo_orderkey` UInt32, `lo_linenumber` UInt8, `lo_custkey` UInt32, `lo_partkey` UInt32, `lo_suppkey` UInt32, `lo_orderdate` Date, … `p_color` LowCardinality(String), `p_type` LowCardinality(String), `p_size` UInt8, `p_container` LowCardinality(String) ) ENGINE = Distributed('ssb_test', 'ssb_100g', 'lineorder_flat_local', lo_orderkey) CREATE TABLE ssb_100g.lineorder_flat_local ( `lo_orderkey` UInt32, `lo_linenumber` UInt8, `lo_custkey` UInt32, … ) ENGINE = MergeTree PARTITION BY toYear(lo_orderdate) ORDER BY (lo_orderdate, lo_orderkey) SETTINGS index_granularity = 8192 │

doris語法更接近mysql;

可以設置dor.. key

doris中的三種存儲模型:

  • 明細模型 - 跟clickhouse中的mergetree類似
  • 聚合模型 - 適用於實時聚合
  • 更新模型 - 對主鍵的覆蓋等

選擇拍序列

分區分桶的設置

 

如何優化SSB測試 — 建表最佳實踐

ClickHouse建表

  • LowCardinality 針對低基數字符串的優化⼿段
  • PARTITION BY toYear(lo_orderdate)
  • ORDER BY (lo_orderdate, lo_orderkey)
  • ENGINE = Distributed('ssb_test', 'ssb_100g', 'lineorder_flat_local', lo_orderkey)

DorisDB建表

  • ⾃適應低基數優化不需要顯示指定
  • PARTITION BY RANGE(`lo_orderdate`)
  • DUPLICATE KEY(`lo_orderdate`, `lo_orderkey`)
  • DISTRIBUTED BY HASH(`lo_orderkey`) BUCKETS 48

DorisDB的分區分桶

 

 

按range分區partition

每個partition中按key進行hash,分散到不同的tablet

partition是數據導入和備份恢復的最小邏輯單位;tablet是數據復制和均衡的最小物理單位;

 

分區分桶與裁剪

 

 

優化SSB查詢:
range分區,每個partition分區(做數據的管理)到每個tablet
分桶 - 數據打散,並行度

 

 

 

 

  

 

 

 

 

 

Impala+Kudu和DorisDB的對⽐

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM