數(shù)據(jù)分片(Sharding)是分布式數(shù)據(jù)庫分而治之 (Divide And Conquer) 這一設(shè)計思想的體現(xiàn)飒赃。過去的單機數(shù)據(jù)庫在大數(shù)據(jù)量下往往面臨存儲和 IO 的限制,而分布式數(shù)據(jù)庫則通過數(shù)據(jù)劃分的規(guī)則类少,將數(shù)據(jù)打散分布至不同的機器或節(jié)點上,形成分布式存儲,因此突破了單機存儲空間和 IO 的瓶頸图毕、使庫表數(shù)據(jù)量可以無限拓展。
數(shù)據(jù)分片主要有范圍分片或哈希分片這兩種方式眷唉,而在實際數(shù)據(jù)庫的實現(xiàn)中予颤,往往呈現(xiàn)為分區(qū)和分桶兩種形式。分區(qū)一般是按照時間或其他連續(xù)值對數(shù)據(jù)進行劃分厢破,在執(zhí)行查詢操作時可以通過分區(qū)裁剪過濾不必要的范圍掃描荣瑟,提升執(zhí)行效率,同時也使得對分區(qū)數(shù)據(jù)的增刪改等管理操作更為便捷摩泪。而分桶則是按照某個關(guān)鍵字執(zhí)行哈希運算笆焰,將相同哈希值的數(shù)據(jù)放到一起,這樣可以有效定位數(shù)據(jù)见坑、避免數(shù)據(jù)傾斜嚷掠。
在 Apache Doris 中,同樣也遵從一定的數(shù)據(jù)分布規(guī)則荞驴。數(shù)據(jù)以關(guān)系表(Table)的形式進行呈現(xiàn)不皆,會依次按照先分區(qū)(Partition)、再分桶(Bucket)的方式劃分熊楼,最終在同一個分桶中的數(shù)據(jù)會形成數(shù)據(jù)分片(Tablet)霹娄。Tablet 是 Apache Doris 中多副本高可用、集群間數(shù)據(jù)調(diào)度與均衡的最小物理存儲單位鲫骗。
圖1:Table-Partition-Tablet 之間的關(guān)系
# 現(xiàn)狀與問題
在 Doris 中犬耻,分區(qū)與分桶是如何創(chuàng)建的?我們以一個網(wǎng)站站點的建表實例說明分區(qū)與分桶的創(chuàng)建方式执泰,該網(wǎng)站的站點建表語句如下:
-- 該表記錄了某個時間點枕磁,在某個站點上各個用戶的pv數(shù)據(jù)CREATE TABLE demo.test_tbl( sdate DATE, -- 日期 site INT, -- 站點id city VARCHAR(64), -- 城市 user VARCHAR(32) DEFAULT '', -- 用戶名 pv BIGINT -- pv量) ENGINE=olap DUPLICATE KEY(sdate, site, city)[PARTITION_DESC][BUCKET_DESC]PROPERTIES ("replication_num" = "1");
其中 [PARTITION_DESC] 表示創(chuàng)建分區(qū)的詳細語句,[BUCKET_DESC] 表示創(chuàng)建分桶的語句术吝。
創(chuàng)建分區(qū)
Apache Doris 支持兩種分區(qū)形式计济,List Partition 與 Range Partition。
List Partition
List Partition 相當于對分區(qū)的列值進行枚舉排苍,因此選擇的分區(qū)列最好是有區(qū)分度的可枚舉值沦寂,例如本例中的 city。根據(jù) city 列的枚舉值創(chuàng)建多個 List Partition纪岁,則 PARTITION_DESC
可以寫為:
-- 以city作為分區(qū)列凑队,創(chuàng)建華北、東北、華中漩氨、西南等分區(qū)PARTITION BY LIST(city)( PARTITION `p_huabei` VALUES IN ("beijing", "tianjin", "shijiazhuang"), PARTITION `p_dongbei` VALUES IN ("shenyang", "dalian"), PARTITION `p_huazhong` VALUES IN ("wuhan", "changsha") PARTITION `p_xinan` VALUES IN ("chengdu", "chongqing"))
Range Partition
創(chuàng)建 Range partition 一般使用時間列西壮,Range Partition 又可以分為靜態(tài)和動態(tài)兩種方式:
- 靜態(tài) Range Partition
此類 Partition 的創(chuàng)建會生成一個左閉右開的區(qū)間,定義一個分區(qū)只需要指定右邊界叫惊,該分區(qū)的左邊界由上一個分區(qū)的右邊界確定款青,PARTITION_DESC
可以寫為:
-- 以sdate這個時間列作為分區(qū)列,-- 日期處于[min, 2023-01-01)的數(shù)據(jù)霍狰,都放到名為p2022的分區(qū)下抡草;-- 日期處于[2023-01-01, 2023-01-02)的數(shù)據(jù),都放到名為p20230101的分區(qū)下蔗坯;-- 日期處于[2023-01-02, 9999-12-31)的數(shù)據(jù)康震,都放到名為pmax的分區(qū)下;PARTITION BY RANGE(sdate)( PARTITION `p2022` VALUES LESS THAN ("2023-01-01"), PARTITION `p20230101` VALUES LESS THAN ("2023-01-02"), PARTITION `pmax` VALUES LESS THAN ("9999-12-31"))
可以看出宾濒,p20230101 這個分區(qū)的左邊界由 p2022 分區(qū)的右邊界確定腿短,而 pmax 的左邊界由 p20230101 的右邊界確定。需注意的是绘梦,此處為了舉例說明動態(tài)分區(qū)橘忱,使用了一個很大的邊"9999-12-31",實際業(yè)務(wù)中很少會直接創(chuàng)建從 2023-01-02 到 9999-12-31 的分區(qū)卸奉。
- 動態(tài) Range Partition
上述靜態(tài)的分區(qū)需要手動指定邊界钝诚,分區(qū)個數(shù)太多使用起來也不方便。動態(tài) Range Partition 幫助我們解決了這個問題榄棵,只需指定一些分區(qū)的參數(shù)即可動態(tài)創(chuàng)建凝颇,PARTITION_DESC 相對更簡單,只需指定哪個列作為分區(qū)列即可:
PARTITION BY RANGE(sdate)()
剩余參數(shù)需要在PARTITION
進行配置:
PROPERTIES ( "dynamic_partition.enable" = "true", "dynamic_partition.time_unit" = "DAY", "dynamic_partition.start" = "-30", "dynamic_partition.end" = "3", "dynamic_partition.prefix" = "p", "dynamic_partition.create_history_partition"="true", "replication_num" = "1");
動態(tài)分區(qū)參數(shù)說明如下:
創(chuàng)建分桶
分桶在物理層面即數(shù)據(jù)分片(Tablet)疹鳄。在數(shù)據(jù)表完成分區(qū)后祈噪,指定部分列作為分桶列,將這些列數(shù)據(jù)中相同哈希值的數(shù)據(jù)合到一起尚辑,形成了 Tablet。一個表中 Tablet 總數(shù)量 = 分區(qū)數(shù)(Partition num)x 分桶數(shù)(Bucket num)x 數(shù)據(jù)副本數(shù)(Replication_num)盔腔。
[BUCKET_DESC] 語句非常簡單杠茬,只需要一句:
DISTRIBUTED BY HASH(site) BUCKETS 20
此時指定以 site 列的哈希值作為分桶,并且分桶個數(shù)設(shè)置為 20 個弛随,需要注意的是這里的 20 僅作為示例瓢喉,合適的分桶個數(shù)需要根據(jù)分區(qū)大小來確定。實際上單個分桶即 Tablet 的數(shù)據(jù)量理論上沒有上下界舀透,但建議在 1GB - 10GB 的范圍內(nèi)栓票,即假設(shè)分區(qū)大小為 20GB,那么分桶個數(shù)設(shè)置為 10-20 個是合適的。
不足與思考
從以上對分區(qū)分桶的介紹走贪,相信有不少用戶和讀者仍能發(fā)現(xiàn)其中一些不足之處:
- 分區(qū)數(shù)量過多的情況下佛猛,使用 List Partition 或者靜態(tài) Range Partition 會使得 SQL 較為繁瑣,編寫起來費時費力坠狡;
- 若是使用動態(tài) Range Partition继找,則需要掌握多個參數(shù),使用方式不友好且學習成本較高逃沿;而當存在大量歷史冷數(shù)據(jù)來說婴渡,動態(tài) Range Partition 只能指定單一粒度,無法靈活組合不同的分區(qū)粒度凯亮;
- 分桶個數(shù)的設(shè)置十分依賴用戶對 Apache Doris 數(shù)據(jù)分布機制和業(yè)務(wù)數(shù)據(jù)本身的理解边臼,使用門檻較高。不合理的分桶設(shè)置將對系統(tǒng)性能和穩(wěn)定性造成一定程度沖擊:分桶數(shù)太多將導致單個 Tablet 的數(shù)據(jù)量過小假消,數(shù)據(jù)聚合效果不佳柠并、查詢性能不能得到有效發(fā)揮,并且元數(shù)據(jù)管理壓力大置谦;個數(shù)太少則單個 Tablet 包含的數(shù)據(jù)量過大堂鲤,不利于副本的遷移、補齊媒峡,且會增加 Schema Change 或者 Rollup 操作失敗重試的代價瘟栖。
# ****批量分區(qū)與Auto Bucket的設(shè)計與實現(xiàn)
克服數(shù)據(jù)庫的復雜性是 Apache Doris 一直追求的目標之一,針對以上分區(qū)分桶存在的易用性問題谅阿,在 Apache Doris 最新的版本中已經(jīng)得到解決半哟。在 Apache Doris 1.2.1 版本中,我們新增了批量創(chuàng)建分區(qū)功能签餐,簡潔的語法和靈活的使用方式讓批量創(chuàng)建歷史分區(qū)更加得心應(yīng)手寓涨;而針對分桶設(shè)置帶來的學習成本,Apache Doris 在即將發(fā)布的 1.2.2 版本中新增了 Auto Bucket 自動分桶推算功能氯檐,分桶個數(shù)不再依賴于人工設(shè)置戒良,通過規(guī)則的智能計算即可保證合理的數(shù)據(jù)劃分,降低用戶學習成本的同時還可以最大化提升用戶開發(fā)效率冠摄。
批量創(chuàng)建分區(qū)
批量創(chuàng)建分區(qū)功能在前期充分調(diào)研了用戶的需求糯崎,本著簡潔、強大河泳、易用的設(shè)計目標沃呢,將設(shè)計核心鎖定在幾個要素中:
- 時間區(qū)間范圍(會考慮開閉問題)
- 時間跨度(即每個分區(qū)的時間維度的大小)
- 時間單位(年拆挥、月薄霜、日、時、周等)
結(jié)合前面提到的網(wǎng)站站點模型惰瓜,假設(shè)其數(shù)據(jù)包含從幾年前直到現(xiàn)在的全量信息否副,想要將十年內(nèi)的數(shù)據(jù)按每一天一個分區(qū)進行創(chuàng)建。在批量分區(qū)功能中鸵熟,PARTITION_DESC
只需要一句副编,并且不用在PARTITION
中設(shè)置分區(qū)相關(guān)參數(shù):
-- 當然,分區(qū)創(chuàng)建個數(shù)受到max_multi_partition_num參數(shù)控制流强,該值默認為4096痹届,有需求可以修改PARTITION BY RANGE(sdate)( FROM ("2013-01-01") TO ("2023-01-01") INTERVAL 1 DAY)從這個 case 來看,批量分區(qū)功能的語法更為簡潔打月,但該功能的易用性和靈活性遠不止于此队腐。
從這個 case 來看,批量分區(qū)功能的語法更為簡潔奏篙,但該功能的易用性和靈活性遠不止于此柴淘。
假設(shè)有另一批數(shù)據(jù):公司前幾年的數(shù)據(jù)量較大且為冷數(shù)據(jù),故可以將一年的數(shù)據(jù)合到一個分區(qū)里面秘通;而后來因為業(yè)務(wù)迅速發(fā)展为严,需要將每一月的數(shù)據(jù)作為一個分區(qū);隨著公司業(yè)務(wù)進一步發(fā)展肺稀,按月分區(qū)已經(jīng)不能滿足快速增長的數(shù)據(jù)需求第股,需要按周進行分區(qū);……话原;時至今日夕吻,公司每天產(chǎn)生海量數(shù)據(jù),可能需要按小時分區(qū)才能符合需求繁仁。根據(jù)這個場景涉馅,不難寫出批量分區(qū)創(chuàng)建的 PARTITION_DESC:
-- 此處需要注意,如果要使用小時級別的分區(qū)黄虱,則分區(qū)列必須是datetime類型-- 同樣的稚矿,分區(qū)創(chuàng)建個數(shù)也受到max_multi_partition_num參數(shù)控制PARTITION BY RANGE(sdate)( FROM ("2000-01-01") TO ("2021-01-01") INTERVAL 1 YEAR, FROM ("2021-01-01") TO ("2022-01-01") INTERVAL 1 MONTH, FROM ("2022-01-01") TO ("2023-01-01") INTERVAL 1 WEEK, FROM ("2023-01-01") TO ("2023-02-01") INTERVAL 1 DAY, FROM ("2023-02-01 00") TO ("2099-12-31 23") INTERVAL 1 HOUR)
除了上述不同時間粒度的分區(qū)可以靈活組合外,還可以將靜態(tài) Range Partition 和批量分區(qū)功能結(jié)合起來捻浦。例如需要將該公司 2022-01-01 到 2023-01-01 的數(shù)據(jù)按天創(chuàng)建分區(qū)盐捷,2022-01-01 之前的數(shù)據(jù)歸到一個名為"pold"分區(qū)中,我們可以將靜態(tài)分區(qū)和批量分區(qū)組合起來默勾,PARTITION_DESC如下:
PARTITION BY RANGE(sdate)( PARTITION pold VALUES LESS THAN ("2022-01-01"), FROM ("2022-01-01") TO ("2023-01-01") INTERVAL 1 DAY)
批量分區(qū)創(chuàng)建功能支持不同時間粒度,其語法簡潔有力聚谁,且各種類型分區(qū)可以靈活組合母剥,在面對大量歷史分區(qū)和部分特殊分區(qū)的需求時,該功能顯得游刃有余,可以極大提高開發(fā)效率环疼。批量分區(qū)功能 PR:https://github.com/apache/doris/pull/13772
Auto Bucket 自動分桶推算
以往創(chuàng)建分桶時需要手動設(shè)定分桶數(shù)习霹,而自動分桶推算功能是 Apache Doris 可以動態(tài)地推算分桶個數(shù),使得分桶數(shù)始終保持在一個合適范圍內(nèi)炫隶,讓用戶不再操心桶數(shù)的細枝末節(jié)淋叶。首先說明一點,為了方便闡述該功能伪阶,該部分會將桶拆分為兩個時期的桶煞檩,即初始分桶以及后續(xù)分桶。(這里的初始和后續(xù)只是本文為了描述清楚該功能而采用的術(shù)語栅贴,Apache Doris 分桶本身沒有初始和后續(xù)之分)從上文中創(chuàng)建分桶一節(jié)我們知道斟湃,BUCKET_DESC
非常簡單,但是需要指定分桶個數(shù)檐薯;而在自動分桶推算功能上凝赛,BUCKET_DESC
的語法直接將分桶數(shù)改成"Auto",并新增一個 Properties 配置即可:
-- 舊版本指定分桶個數(shù)的創(chuàng)建語法DISTRIBUTED BY HASH(site) BUCKETS 20-- 新版本使用自動分桶推算的創(chuàng)建語法DISTRIBUTED BY HASH(site) BUCKETS AUTOproperties("estimate_partition_size" = "100G")
新增的配置參數(shù)estimate_partition_size
表示一個單分區(qū)的數(shù)據(jù)量坛缕。該參數(shù)是可選的墓猎,如果沒有給出則 Doris 會將 estimate_partition_size 的默認值取為 10GB。從上文中已經(jīng)得知赚楚,一個分桶在物理層面就是一個Tablet毙沾,為了獲得最好的性能,建議 Tablet 的大小在**1GB - 10GB **的范圍內(nèi)直晨。那么自動分桶推算是如何保證 Tablet 大小處于這個范圍內(nèi)的呢搀军?總結(jié)起來不外乎幾個原則:
- 若是整體數(shù)據(jù)量較小,則分桶數(shù)不要設(shè)置過多
- 若是整體數(shù)據(jù)量較大勇皇,則應(yīng)使桶數(shù)跟總的磁盤塊數(shù)相關(guān)罩句,充分利用每臺 BE 機器和每塊磁盤的能力
初始分桶推算
從原則出發(fā),理解自動分桶推算功能的詳細邏輯就變得簡單了:首先來看初始分桶:
1. 先根據(jù)數(shù)據(jù)量得出一個桶數(shù) N敛摘。首先使用 estimate_partition_size 的值除以 5(按文本格式存入 Doris 中有 5 比 1 的數(shù)據(jù)壓縮比計算)门烂,得到的結(jié)果為:
- < 100MB,則取 N=1
- < 1GB兄淫,則取 N=2
= 1GB屯远,則每一個 GB 一個分桶
2. 根據(jù) BE 節(jié)點數(shù)以及每個 BE 節(jié)點的磁盤容量,計算出桶數(shù) M捕虽。其中每個 BE 節(jié)點算 1慨丐,每 50G 的磁盤容量算 1,那么 M 的計算規(guī)則為:*M = BE 節(jié)點數(shù) ( 一塊磁盤塊大小 / 50GB) * 磁盤塊數(shù)泄私,例如有 3 臺 BE房揭,每臺 BE 都有 4 塊 500GB 的磁盤备闲,那么 M = 3 * (500GB / 50GB) * 4 = 1203. 得到最終的分桶個數(shù)計算邏輯:
- 先計算一個中間值 x = min(M, N, 128),
- 如果 x < N并且x < BE節(jié)點個數(shù)捅暴,則最終分桶為 y 即 BE 節(jié)點個數(shù)恬砂;否則最終分桶數(shù)為 x
上述過程偽代碼表現(xiàn)形式為:
int N = 計算N值;int M = 計算M值;int y = BE節(jié)點個數(shù);int x = min(M, N, 128);if (x < N && x < y) { return y;}return x;
有了上述算法,咱們再引入一些例子來更好地理解這部分邏輯:
case 1:
*數(shù)據(jù)量 100 MB蓬痒,10 臺 BE 機器泻骤,2TB * 3 塊盤 *
*數(shù)據(jù)量 N = 1 *
BE 磁盤 M = 10 * (2TB/50GB) * 3 = 1230
*x = min(M, N, 128) = 1 *
最終: 1
**case 2: **
*數(shù)據(jù)量 1GB, 3 臺 BE 機器,500GB * 2 塊盤 **數(shù)據(jù)量 N = 2 **BE 磁盤 M = 3 * (500GB/50GB) * 2 = 60 **x = min(M, N, 128) = 2 **最終: 2 *
case 3:
*數(shù)據(jù)量 100GB梧奢,3 臺 BE 機器狱掂,500GB * 2 塊盤 **數(shù)據(jù)量 N = 20 **BE 磁盤 M = 3 * (500GB/50GB) * 2 = 60 **x = min(M, N, 128) = 20 **最終: 20 case 4:數(shù)據(jù)量 500GB,3 臺 BE 機器粹断,1TB * 1 塊盤 **數(shù)據(jù)量 N = 100 **BE 磁盤 M = 3 * (1TB /50GB) * 1 = 60 **x = min(M, N, 128) = 63 **最終: 63 case 5:數(shù)據(jù)量 500GB符欠,10 臺 BE 機器,2TB * 3 塊盤 **數(shù)據(jù)量 N = 100 **BE 磁盤 M = 10 * (2TB / 50GB) * 3 = 1230 **x = min(M, N, 128) = 100 **最終: 100 case 6:數(shù)據(jù)量 1TB瓶埋,10 臺 BE 機器希柿,2TB * 3 塊盤 **數(shù)據(jù)量 N = 205 **BE 磁盤 M = 10 * (2TB / 50GB) * 3 = 1230 **x = min(M, N, 128) = 128 **最終: 128 case 7:數(shù)據(jù)量 500GB,1 臺 BE 機器养筒,100TB * 1 塊盤 **數(shù)據(jù)量 N = 100 **BE 磁盤 M = 1 * (100TB / 50GB) * 1 = 2048 **x = min(M, N, 128) = 100 **最終: 100 case 8:數(shù)據(jù)量 1TB, 200 臺 BE 機器曾撤,4TB * 7 塊盤 **數(shù)據(jù)量 N = 205 **BE 磁盤 M = 200 * (4TB / 50GB) * 7 = 114800 **x = min(M, N, 128) = 128 *最終: 200
可以看到,詳細邏輯與原則是匹配的晕粪。
后續(xù)分桶推算
上述是關(guān)于初始分桶的計算邏輯挤悉,后續(xù)分桶數(shù)因為已經(jīng)有了一定的分區(qū)數(shù)據(jù),可以根據(jù)已有的分區(qū)數(shù)據(jù)量來進行評估巫湘。后續(xù)分桶數(shù)會根據(jù)最多前 7 個分區(qū)數(shù)據(jù)量的 EMA[1](短期指數(shù)移動平均線)值装悲,作為estimate_partition_size
進行評估。此時計算分桶有兩種計算方式尚氛,假設(shè)以天來分區(qū)诀诊,往前數(shù)第一天分區(qū)大小為 S7,往前數(shù)第二天分區(qū)大小為 S6阅嘶,依次類推到 S1属瓣;
- 如果 7 天內(nèi)的分區(qū)數(shù)據(jù)每日嚴格遞增,則此時會取趨勢值
有6個delta值讯柔,分別是S7 - S6 = delta1,S6 - S5 = delta2,...S2 - S1 = delta6由此得到平均的delta值:avg_delta = (delta1 + delta2 + ... + delta6) / 6 = (S7 - S1) / 6那么抡蛙,今天的estimate_partition_size = S7 + avg_delta
- 非第一種的情況,此時直接取前幾天的 EMA 平均值
今天的 estimate_partition_size = EMA(S1, ..., S7)
根據(jù)上述算法魂迄,初始分桶個數(shù)以及后續(xù)分桶個數(shù)都能被計算出來粗截。跟之前只能指定固定分桶數(shù)不同,由于業(yè)務(wù)數(shù)據(jù)的變化捣炬,有可能前面分區(qū)的分桶數(shù)和后面分區(qū)的分桶數(shù)不一樣慈格,這對用戶是透明的怠晴,用戶無需關(guān)心每一分區(qū)具體的分桶數(shù)是多少,而這一自動推算的功能會讓分桶數(shù)更加合理浴捆。
自動分桶推算功能 PR:https://github.com/apache/doris/pull/15250
效果
當我們有了合適的分區(qū)分桶時,導入數(shù)據(jù)導到 Doris 后稿械,數(shù)據(jù)會依照建表語句中的分區(qū)分桶列進行存儲选泻。上述網(wǎng)站站點數(shù)據(jù)的存儲示例如圖示:圖2:Doris 分區(qū)分桶后的數(shù)據(jù)存儲此時如果執(zhí)行 SQL 查詢:
select * from test_tbl where sdate = "2020-03-23" and site = 1
根據(jù)謂詞 sdate = "2020-03-23" 可以定位到分區(qū) p20200323,謂詞 site = 1 能定位到該分區(qū)下的 bucket_1美莫。假設(shè)有 30 天數(shù)據(jù)页眯,自動分桶推算得到的分桶個數(shù)為 20 個。則經(jīng)過明確的分區(qū)分桶謂詞下推厢呵,則可以將數(shù)據(jù)全表掃描量變?yōu)樵瓉淼?1/600(30 天20 個桶 = 600)窝撵,極大減少了數(shù)據(jù)的掃描范圍、提高了查詢的效率*襟铭。
# 總結(jié)
整體來看碌奉,批量創(chuàng)建分區(qū)功能語法簡潔有力,解決了用戶針對大量歷史數(shù)據(jù)分區(qū)創(chuàng)建的難題寒砖,既避免了手動創(chuàng)建大量分區(qū)的低效語法赐劣,又避免了動態(tài)分區(qū)大量參數(shù)的學習使用成本,且方式靈活多變哩都、隨意搭配組合各種類型的分區(qū)魁兼,大大提升了 Doris 在建表過程中的易用性。自動分桶推斷功能智能高效漠嵌,用戶不需再關(guān)心分桶的細枝末節(jié)咐汞,系統(tǒng)自動幫助用戶擴縮不同分區(qū)的分桶數(shù),真正做到桶隨業(yè)務(wù)變儒鹿,降低學習成本的同時更是提升了查詢效率化撕。在與社區(qū)用戶持續(xù)溝通中,我們也不斷收獲著許多新的需求挺身,例如分區(qū)列為非時間列等侯谁,因此后續(xù)我們?nèi)詫⒗^續(xù)完善對其他分區(qū)列的支持,例如數(shù)字分區(qū)列的批量創(chuàng)建等章钾。最后墙贱,我們期待傾聽更多用戶的聲音,在不斷回饋用戶以極簡易用的使用體驗的同時贱傀,也期待有更多人參與到 Apache Doris 的建設(shè)中來惨撇,歡迎你的加入!