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的對⽐