劃與調(diào)優(yōu)實戰(zhàn))
凌晨兩點我盯著屏幕上那行“Column order_id cannot be resolved”的報錯Presto集群的元數(shù)據(jù)緩存又沒跟上。那一刻我決定下一套報表平臺直接搭在Doris上。如果你也在Presto和Doris之間舉棋不定或者正準(zhǔn)備做Doris安裝部署和集群部署這篇內(nèi)容可以幫你少走不少彎路。我會從單機跑起來開始一直講到生產(chǎn)集群的規(guī)劃、遷移SQL時遇到的“missing”問題以及運行半年后沉淀下來的調(diào)優(yōu)清單。1. 先從一次“missing”報錯說起為什么我不再讓Presto跑核心報表1.1 一次凌晨報表任務(wù)的完整排查鏈路那是一個常規(guī)的日報任務(wù)凌晨兩點由Presto集群調(diào)度執(zhí)行。SQL本身不復(fù)雜從一張訂單明細表里按城市分組統(tǒng)計GMV關(guān)聯(lián)一張用戶維度表取注冊時間。問題出在關(guān)聯(lián)之后Presto報了一個讓我當(dāng)時很頭疼的錯誤——Column order_id cannot be resolved。我當(dāng)時的排查鏈路是這樣的第一步檢查SQL文本。SELECT里確實沒有引用order_id誤寫不成立。第二步單獨查字段。SELECT order_id FROM 訂單表 LIMIT 1能跑通說明底層表結(jié)構(gòu)里有這一列。第三步懷疑是表結(jié)構(gòu)變更。去查元數(shù)據(jù)管理服務(wù)發(fā)現(xiàn)這張表在凌晨一點多剛做過一次schema更新新增了一個字段而Presto連接器緩存的元數(shù)據(jù)沒有及時刷新。第四步在Presto端刷新元數(shù)據(jù)緩存重新執(zhí)行任務(wù)恢復(fù)。整個過程花了大概四十分鐘。問題本身不復(fù)雜但這類“元數(shù)據(jù)不同步導(dǎo)致的missing”在Presto聯(lián)邦查詢架構(gòu)里非常折磨人查詢引擎、元數(shù)據(jù)服務(wù)、底層存儲是三個獨立的系統(tǒng)任何一個環(huán)節(jié)緩存滯后你都會看到莫名其妙的列或表解析失敗。后來我把同一套報表遷到了Doris上。同樣的SQL在Doris里直接跑通不會再出現(xiàn)“某個列突然消失”的情況。因為Doris是存儲與計算一體的OLAP數(shù)據(jù)庫元數(shù)據(jù)和數(shù)據(jù)在同一個集群里建表、刪列、查詢走的是同一套MySQL協(xié)議入口不存在連接器緩存漂移的問題。1.2 Doris的定位它和Presto、ClickHouse的關(guān)鍵差異很多人把Doris和Presto放在同一個籃子里比較其實它們是兩種不同的東西。Presto是一個分布式SQL查詢引擎本身不存數(shù)據(jù)。它通過連接器去讀Hive、HDFS、S3、MySQL等各種數(shù)據(jù)源優(yōu)勢是靈活適合做聯(lián)邦查詢、數(shù)據(jù)湖分析。劣勢也很明顯沒有自己的存儲查詢性能取決于下游數(shù)據(jù)源的組織方式元數(shù)據(jù)鏈路長容易出現(xiàn)前面說的“missing”類問題。Doris則是完整的MPP分析型數(shù)據(jù)庫。它有自己的列式存儲引擎、向量化執(zhí)行引擎、CBO優(yōu)化器同時兼容MySQL協(xié)議。數(shù)據(jù)導(dǎo)入之后查詢直接在Doris內(nèi)部完成不需要跨系統(tǒng)拉數(shù)據(jù)。ClickHouse是另一個常被拿來對比的列存數(shù)據(jù)庫。ClickHouse單機查詢性能非常強但在集群運維、join能力、精確去重這些方面團隊需要付出的精力更多。Doris在分布式j(luò)oin、高并發(fā)點查、多表關(guān)聯(lián)這些場景上更均衡一些而且建表、導(dǎo)入、權(quán)限管理都做得比較完善。我用一張表把三者的差異理順維度PrestoDorisClickHouse是否自帶存儲否依賴外部數(shù)據(jù)源是列式存儲是列式存儲元數(shù)據(jù)一致性多系統(tǒng)協(xié)同易緩存延遲存儲計算一體一致性高存儲計算一體一致性較高SQL兼容ANSI SQL但分?jǐn)?shù)據(jù)源方言MySQL協(xié)議習(xí)慣成本低SQL方言較特殊適用場景數(shù)據(jù)湖、聯(lián)邦查詢BI報表、多維分析、明細查詢單機超高性能查詢、寬表聚合集群運維復(fù)雜度中中低中高尤其副本和分布式DDL一句話總結(jié)如果你需要的是“一個能穩(wěn)定跑報表、少出幺蛾子的分析型數(shù)據(jù)庫”Doris是很順手的選擇。1.3 我在什么場景下會堅定選DorisDoris官方定位是“面向分析的高性能分布式數(shù)據(jù)庫”我用了半年之后把它適用場景歸納為三類BI報表與看板。MySQL協(xié)議對數(shù)據(jù)部門和后端工程師太友好了任何語言連MySQL的方式都能直接連Doris不用額外寫驅(qū)動。明細查詢與聚合混合負載。既能用主鍵查單條記錄也能跑大范圍聚合不需要搭兩套系統(tǒng)。需要精確去重和多表join的統(tǒng)計場景。比如UV統(tǒng)計、GMV匯總、漏斗分析Doris在這類場景的穩(wěn)定性和性能都比Presto更可控。另外值得一提的是Doris的導(dǎo)入生態(tài)支持Stream Load、Broker Load、Routine Load、Insert Into等多種方式和Kafka、HDFS、Flink、Spark的集成都比較成熟。對于中小團隊來說一套Doris集群可以替代“Presto Hive 一套OLAP庫”的組合架構(gòu)簡單很多維護成本也低很多。2. 單機版先跑起來Doris安裝部署從下載到建表2.1 下載與版本選擇LTS優(yōu)先別追新我第一次部署時直接選了當(dāng)時最新的版本結(jié)果被一些小問題折騰得夠嗆。后來學(xué)乖了優(yōu)先選LTS版本或已發(fā)布較久的stable版本不建議拿剛發(fā)的小版本直接上生產(chǎn)。從Doris官網(wǎng)下載二進制安裝包時注意確認操作系統(tǒng)和CPU架構(gòu)。官方提供x64和ARM的包選錯了解壓啟動后會遇到非法指令這類問題。我用的版本文件類似apache-doris-2.1.x-bin-x64.tar.gz里面已經(jīng)包含了FE、BE、Broker等組件不需要自己編譯。非特殊情況不要自己去從源碼編譯費時費力不說還容易缺依賴。下載到服務(wù)器后解壓到統(tǒng)一目錄比如/opt/apache-doris/然后分別進到fe和be子目錄做配置和啟動。2.2 部署前的系統(tǒng)環(huán)境準(zhǔn)備這幾項不做后面全是坑Doris對系統(tǒng)環(huán)境的要求不算苛刻但有幾項必須提前處理否則啟動過程會非常痛苦。JDK版本FE依賴Java運行環(huán)境建議JDK 8或JDK 11。BE是C實現(xiàn)不需要Java。文件句柄數(shù)BE需要打開大量文件默認的ulimit -n往往不夠。建議設(shè)置成65535以上順便把max user processes也調(diào)大。swap策略建議關(guān)閉或盡量降低swap使用。分析型查詢對延遲敏感一旦發(fā)生內(nèi)存換頁查詢耗時可能瞬間翻倍。時鐘同步集群內(nèi)所有節(jié)點要保持時間同步建議部署NTP服務(wù)。時間偏移會導(dǎo)致BE心跳異常、元數(shù)據(jù)判斷出錯。我部署時的經(jīng)驗是先把這些系統(tǒng)參數(shù)寫入/etc/security/limits.conf再重啟服務(wù)器或者至少重啟登錄會話確保生效。別省這一步否則后面排查“BE狀態(tài)異?!睍ǖ魩讉€小時。2.3 啟動FE與BE偽分布式跑通只需幾分鐘單機部署時FE和BE可以放在同一臺機器上。雖然生產(chǎn)環(huán)境不推薦這樣但用于學(xué)習(xí)、功能驗證、給團隊做Demo完全夠用。啟動FEcd /opt/apache-doris/fe ./bin/start_fe.sh --daemonFE默認端口是8030HTTP、9030MySQL協(xié)議、9010edit log、9020Thrift RPC。這一步如果用默認端口不用改配置就能直接啟動成功。接著用MySQL客戶端連接FEmysql -h127.0.0.1 -P9030 -uroot看到Welcome to the MySQL monitor說明FE已經(jīng)起來了。接下來啟動BEcd /opt/apache-doris/be ./bin/start_be.sh --daemonBE啟動后不會自動注冊到FE需要手動添加一次。在MySQL客戶端里執(zhí)行ALTER SYSTEM ADD BACKEND 127.0.0.1:9050;然后看一下BE狀態(tài)SHOW PROC /backends;重點看最后一列的Alive字段如果顯示true單機版就已經(jīng)跑通了。提示BE的9050是心跳端口不是數(shù)據(jù)端口。添加BE時填的IP和端口必須和BE節(jié)點自己上報的地址一致否則會報“backend not found”之類的錯誤。2.4 建表與導(dǎo)入第一份數(shù)據(jù)先跑通一個完整流程單機版跑起來之后我建議立刻建一張表、導(dǎo)一份數(shù)據(jù)進去把整個鏈路走一遍。這一步能幫你快速驗證部署是否正常也能讓你直觀感受到Doris的SQL習(xí)慣。建庫建表CREATE DATABASE test_db; CREATE TABLE test_db.orders ( order_id BIGINT NOT NULL, user_id BIGINT NOT NULL, city VARCHAR(32), amount DECIMAL(12, 2), status TINYINT, order_time DATETIME ) DUPLICATE KEY(order_id) PARTITION BY RANGE(order_time) () DISTRIBUTED BY HASH(user_id) BUCKETS 12 PROPERTIES ( replication_num 1 );先說明一下這個建表語句里幾個關(guān)鍵詞的含義DUPLICATE KEY表示明細模型適合保存原始訂單數(shù)據(jù)PARTITION BY RANGE按時間分區(qū)方便后續(xù)按日期裁剪DISTRIBUTED BY HASH按用戶ID分桶確保同一個用戶的數(shù)據(jù)落到同一個分桶里join和聚合時可以減少跨節(jié)點數(shù)據(jù)移動。單機版replication_num設(shè)為1即可生產(chǎn)環(huán)境通常設(shè)為2或3。導(dǎo)入數(shù)據(jù)使用Stream Load方式這是Doris最常用的本地導(dǎo)入方式curl --location-trusted -u root: \ -H label:test_order_001 \ -H column_separator:, \ -H format:csv_with_names \ -H max_filter_ratio:0.05 \ -T /data/orders.csv \ http://127.0.0.1:8030/api/test_db/orders/_stream_loadlabel是導(dǎo)入事務(wù)的唯一標(biāo)識同一張表里不能重復(fù)。max_filter_ratio允許一定比例的錯誤數(shù)據(jù)通過避免因為個別臟數(shù)據(jù)導(dǎo)致整個文件導(dǎo)入失敗。2.5 單機環(huán)境必須驗證的幾個點部署完成不等于萬事大吉。我每次搭完環(huán)境都會做一組“自檢清單”大概十幾分鐘能省掉后面很多排查時間看FE和BE日志。FE日志在fe/log/fe.logBE日志在be/log/be.INFO啟動報錯基本都會留在這里。執(zhí)行SHOW PROC /backends確認所有BE都是Alive狀態(tài)。執(zhí)行SHOW TABLET FROM test_db.orders查看副本狀態(tài)正常應(yīng)該是health為true。跑一條簡單查詢SELECT city, SUM(amount) FROM test_db.orders GROUP BY city確認向量化執(zhí)行沒有報錯。用EXPLAIN SELECT ...看一眼執(zhí)行計劃確認分區(qū)裁剪和分桶裁剪生效而不是全表掃描。這套自檢流程我后來在每一套集群上線前都會執(zhí)行一遍比直接跑業(yè)務(wù)SQL更容易暴露底層問題。3. 上生產(chǎn)前的集群規(guī)劃FE與BE的角色分工和部署細節(jié)3.1 先想清楚要多少臺機器很多人部署Doris集群時第一個問題就是“要幾臺機器”。我給一個比較務(wù)實的估算方式。首先要明白FE和BE的定位FE是大腦負責(zé)元數(shù)據(jù)管理、查詢解析、生成執(zhí)行計劃BE是肌肉負責(zé)數(shù)據(jù)存儲和真正的計算。BE的負載遠高于FE所以機器資源要向BE傾斜。我常用的規(guī)劃思路是數(shù)據(jù)總量在幾十TB以內(nèi)3臺BE起步每臺配16核64G或32核128G。FE建議至少3個節(jié)點組成高可用組。如果只是開發(fā)和測試環(huán)境用3臺機器每臺上面跑一個FE加一個BE勉強能支撐。但生產(chǎn)環(huán)境我不建議把FE和BE混部特別是BE負載高的場景會互相影響。磁盤方面BE的數(shù)據(jù)目錄建議使用SSD。Doris的列式存儲和點查場景對隨機IO有要求SSD和機械盤的查詢時延差距非常明顯。同時要為BE預(yù)留至少20%的空余磁盤否則compaction和導(dǎo)入會撐不住。3.2 FE集群Follower、Observer與元數(shù)據(jù)一致性FE有兩種角色Follower和Observer。Follower參與元數(shù)據(jù)選舉Observer只提供查詢服務(wù)不參與選舉。生產(chǎn)中通常部署1個Follower作為主節(jié)點再加2個Follower組成高可用如果讀壓力大再加Observer擴展。在已啟動的Master FE上執(zhí)行ALTER SYSTEM ADD FOLLOWER fe2_host:9010; ALTER SYSTEM ADD OBSERVER fe3_host:9010;然后在新節(jié)點的fe/conf/fe.conf里保證meta_dir配置一致執(zhí)行啟動命令時帶上Master的地址cd /opt/apache-doris/fe ./bin/start_fe.sh --helper master_host:9010 --daemon這里有個關(guān)鍵點FE的元數(shù)據(jù)是極其重要的資產(chǎn)。整個集群的庫表結(jié)構(gòu)、分區(qū)分桶、副本分布都記錄在meta_dir里建議把meta目錄放到獨立磁盤上并定期備份。我第一次升級集群時因為疏忽FE元數(shù)據(jù)所在磁盤滿掉導(dǎo)致整個集群短暫不可用從那之后我把meta目錄的磁盤監(jiān)控提到了最高優(yōu)先級。3.3 BE的擴容與副本重新平衡往集群里加BE很簡單ALTER SYSTEM ADD BACKEND be2_host:9050;加完之后Doris會自動進行tablet的負載均衡把一部分?jǐn)?shù)據(jù)從舊的BE挪到新的BE上。觀察進度可以用SHOW PROC /cluster_balance;這個表里能看到tablet在BE之間的移動狀態(tài)。剛掛上新的BE時你會發(fā)現(xiàn)集群性能沒有立刻提升反而可能因為數(shù)據(jù)搬遷占用IO而輕微下降這是正?,F(xiàn)象等均衡完成后才會整體變好。我踩過的一個坑是擴容前沒有注意磁盤容量差異。BE節(jié)點之間磁盤大小不一樣時Doris按容量做均衡的效果會打折扣容易出現(xiàn)某個大磁盤的BE還是偏空閑小磁盤的BE已經(jīng)快滿了。所以規(guī)劃BE機器時盡量保持磁盤規(guī)格一致。3.4 端口清單與網(wǎng)絡(luò)配置的避坑指南多節(jié)點部署時網(wǎng)絡(luò)端口放通是第一步。我以默認配置為例列一下需要放通的端口組件端口用途FE8030FE HTTP服務(wù)用于頁面和導(dǎo)入FE9030MySQL協(xié)議連接端口FE9010FE節(jié)點間edit log通信FE9020FE Thrift RPCBE9050BE心跳上報BE9060BE Thrift RPCBE8040BE HTTP服務(wù)BE8060BRPC服務(wù)具體端口可能隨版本微調(diào)部署前以官方文檔對應(yīng)版本的參數(shù)說明為準(zhǔn)。但要注意FE與FE之間、FE與BE之間、BE與BE之間的網(wǎng)絡(luò)必須全通不能只放通客戶端到FE的端口。否則你會遇到“BE狀態(tài)正常但查詢報錯”這種非常隱晦的問題。3.5 部署過程中最容易踩到的三個坑我在多次集群部署里踩過的坑大致可以歸成三類分享出來希望大家繞開。第一內(nèi)存參數(shù)沒有顯式設(shè)置。BE默認的mem_limit可能高達機器物理內(nèi)存的90%這個值在生產(chǎn)環(huán)境偏大。操作系統(tǒng)需要留內(nèi)存給page cacheBE和其他進程也需要呼吸空間。我一般顯式設(shè)置成物理內(nèi)存的70%-80%再根據(jù)負載微調(diào)。第二FE和BE混布導(dǎo)致資源爭搶。單機測試沒問題但生產(chǎn)環(huán)境如果BE在跑大查詢FE的響應(yīng)會明顯變慢元數(shù)據(jù)操作都跟著受影響。有條件的話FE用獨立機器哪怕配置低一點也沒關(guān)系。第三BE磁盤寫滿導(dǎo)致節(jié)點自動下線。Doris檢測到BE數(shù)據(jù)目錄不可寫或剩余空間不足時可能主動把BE標(biāo)記為不可用。我見過太多因為日志沒有清理、數(shù)據(jù)目錄被灌滿導(dǎo)致的“集群突然掛掉”事件。上線前務(wù)必給BE的數(shù)據(jù)目錄和日志目錄配好監(jiān)控告警。4. 遷移SQL到Doris被Presto慣壞之后我踩過的“missing”坑4.1 先說結(jié)論Presto里報“missing”到底是怎么回事“presto doris錯誤的missing”這個關(guān)鍵詞不是第一次出現(xiàn)在我的視野里。用Presto讀Doris的場景最常見的報錯有兩種Column xxx cannot be resolved和Table xxx not found。我和團隊排查過多個這樣的問題根因基本集中在下面三類。第一類是元數(shù)據(jù)緩存不一致。Presto通過連接器訪問Doris時會把表的schema緩存到連接器側(cè)。如果Doris集群里這張表后續(xù)加了列、刪了列或改了類型而Presto側(cè)沒有刷新緩存就會報“列無法解析”。這和我們凌晨那次故障屬于同一類和Doris自身沒關(guān)系純粹是聯(lián)邦查詢架構(gòu)的固有缺陷。第二類是大小寫問題。Presto默認會把SQL里未加引號的標(biāo)識符轉(zhuǎn)成小寫而Doris雖然兼容MySQL協(xié)議但如果你建庫建表時用了大寫字母兩邊對不上就會查不到。解決方案是統(tǒng)一建表規(guī)范要么全部小寫要么在SQL里用反引號強制大小寫。第三類是驅(qū)動和字段類型映射問題。老版本的Doris JDBC驅(qū)動對部分新數(shù)據(jù)類型支持不全或者Presto的Doris連接器對DECIMAL、DATETIME這類類型的映射不完整結(jié)果表現(xiàn)在查詢時就變成“某列不存在”。升級驅(qū)動版本通常能解決。我還想強調(diào)一個很多人忽略的點Presto里報missing的SQL直接拿到Doris執(zhí)行往往根本不會報錯。因為Doris是自己存數(shù)據(jù)的查詢時能直接看到真實的行列結(jié)構(gòu)。所以這類問題最適合的解法就是把這套報表的查詢從Presto遷到Doris來跑而不是在連接器的糾錯上繞圈子。4.2 Doris的SQL寫法與Presto的差異對照把SQL從Presto遷到Doris語法層面整體平滑但還是有幾個需要手工調(diào)整的地方。我整理了一份常用對照表功能Presto寫法Doris寫法時間截斷date_trunc(month, ts)date_trunc(ts, month)2.1版本兩種皆可字符串聚合array_join(array_agg(x), ,)或string_agggroup_concat(x, ,)模糊匹配LIKE同MySQL支持LIKE近似去重approx_distinct(x)approx_count_distinct(x)精確去重用COUNT(DISTINCT x)JSON數(shù)組展開cross join unnest(json_array)LATERAL VIEW explode_json_array(...)列名轉(zhuǎn)義雙引號反引號比較常見的坑是date_trunc的參數(shù)順序。Presto習(xí)慣把時間單位放前面Doris習(xí)慣把時間字段放前面。兩種都寫錯過后來我的做法是統(tǒng)一在Doris里使用DATE_TRUNC(ts, month)這種順序并在SQL注釋里標(biāo)記清楚。另外Doris對反引號的支持更接近MySQL。如果字段名恰好是保留字比如rank、status、desc記得加反引號否則查詢可能直接執(zhí)行失敗。4.3 遷移前必做的三件事把大批SQL從Presto遷到Doris之前我強烈建議先做三件事別急著直接切流。第一用真實的統(tǒng)計SQL跑POC。從業(yè)務(wù)方拿最近一個月的核心查詢SQL在Doris上跑一遍對比行數(shù)和指標(biāo)值。哪怕語法沒問題也要確認指標(biāo)口徑一致尤其是去重計數(shù)、金額保留位數(shù)這些容易產(chǎn)生細微偏差的地方。第二執(zhí)行計劃校驗。對每個核心查詢用EXPLAIN看執(zhí)行計劃確認關(guān)聯(lián)順序、分區(qū)裁剪、分桶裁剪都符合預(yù)期。如果發(fā)現(xiàn)某個大表沒有走分區(qū)裁剪即使查詢能跑通性能和穩(wěn)定性也堪憂。第三壓力測試。模擬幾個并發(fā)用戶同時查報表場景觀察BE的內(nèi)存占用和查詢耗時的波動。很多遷移后的問題不是單查詢跑不動而是并發(fā)上來之后內(nèi)存被打滿觸發(fā)查詢失敗。4.4 遷移后的性能變化一個報表任務(wù)從15分鐘到5分鐘說一個具體的案例。我們有一張20多億行的用戶行為明細表之前用Presto做UV統(tǒng)計和漏斗分析。Presto需要掃描整張表并跨節(jié)點shuffle數(shù)據(jù)一個復(fù)雜的漏斗SQL要跑15分鐘左右而且經(jīng)常遇到資源競爭。遷移到Doris后我把表按事件時間做了分區(qū)把需要高頻聚合的維度建了物化視圖。同樣的SQL在Doris里跑只需要5分鐘左右如果是命中物化視圖的固定指標(biāo)查詢甚至可以壓到10秒以內(nèi)。提速主要來自三方面列式存儲減少無效IO、分區(qū)裁剪縮小掃描范圍、預(yù)聚合避免重復(fù)計算。當(dāng)然也要客觀說一句Doris不是萬能的。如果你的查詢模式是超大數(shù)據(jù)量上的即席探索性分析或者需要經(jīng)常關(guān)聯(lián)數(shù)據(jù)湖里的非結(jié)構(gòu)化文件Presto的靈活性仍然有優(yōu)勢。遷移前先想清楚業(yè)務(wù)的核心訴求是“快”還是“靈活”。5. 運行半年之后我保留下來的Doris調(diào)優(yōu)清單5.1 表模型選錯后面全是被動Doris有三種表模型Duplicate、Unique、Aggregate。很多人剛開始建表時不重視結(jié)果查詢性能差、數(shù)據(jù)更新邏輯不對回來改表結(jié)構(gòu)成本非常高。我現(xiàn)在的選型邏輯很簡單保留明細數(shù)據(jù)且要原始記錄用Duplicate模型。訂單流水、日志明細這類。有更新需求比如維表、用戶狀態(tài)、訂單狀態(tài)用Unique模型。2.0之后的版本默認是Merge-on-Write實現(xiàn)查詢性能比以前的Merge-on-Read好很多。只關(guān)心聚合結(jié)果用Aggregate模型。比如每天匯總的計數(shù)、求和。舉個例子賬單流水表我一開始建成了Unique模型以為按訂單號更新更安全。后來發(fā)現(xiàn)實際上沒有更新需求而Unique模型的寫入開銷比Duplicate大查詢也稍慢白白犧牲了性能。改成Duplicate之后同樣規(guī)模的查詢快了不少。5.2 分區(qū)分桶設(shè)計先按時間分區(qū)再按維度分桶分區(qū)分桶是Doris調(diào)優(yōu)最值得花時間的地方。我的通用做法是先按時間字段做RANGE分區(qū)通常是天或小時再用業(yè)務(wù)維度做HASH分桶確保同一個用戶的記錄集中在一個分桶內(nèi)。分桶數(shù)量的設(shè)置我是按“每個分桶的數(shù)據(jù)量控制在幾百MB左右”來倒推的。分桶太小會產(chǎn)生大量小文件元數(shù)據(jù)和調(diào)度開銷大分桶太大會導(dǎo)致單個桶掃描時間過長并行度不夠。一個大概的經(jīng)驗是初期按集群BE數(shù)量的2-4倍設(shè)置分桶數(shù)后續(xù)根據(jù)實際查詢再調(diào)整。如果表有持續(xù)寫入建議開啟動態(tài)分區(qū)避免每天手動加分區(qū)PROPERTIES ( dynamic_partition.enable true, dynamic_partition.time_unit DAY, dynamic_partition.start -7, dynamic_partition.end 1, dynamic_partition.buckets 12 )start和end控制保留最近多少天的分區(qū)既能滿足報表查詢又不會讓分區(qū)數(shù)量無限膨脹。5.3 慢查詢排錯EXPLAIN和Profile的配合使用遇到慢查詢我先用EXPLAIN看執(zhí)行計劃判斷掃描范圍和join策略是否合理。如果處理不了再開啟Profile看更細粒度的執(zhí)行信息SET is_report_success true;執(zhí)行查詢后在FE的HTTP頁面或者通過API拉取Profile信息。我重點看三個指標(biāo)ScanBytes掃描了多少數(shù)據(jù)。如果很大說明分區(qū)裁剪或分桶裁剪沒生效。PeakMemory查詢峰值內(nèi)存。如果打滿說明join或聚合在某個BE上做了大量shuffle。ExchangeBytes節(jié)點間數(shù)據(jù)傳輸量。這個值越大查詢越慢。常見原因是join鍵選擇不當(dāng)導(dǎo)致大量數(shù)據(jù)被shuffle到不同BE。我遇到過最典型的一個問題大表關(guān)聯(lián)維表維表只有幾十萬行但執(zhí)行計劃里沒有用Broadcast Join而是走了Shuffle Join結(jié)果每次查詢都要在BE之間傳一大堆數(shù)據(jù)。后來在SQL里加上/* BROADCAST */提示耗時直接降了一個數(shù)量級。5.4 寫入側(cè)Stream Load批量導(dǎo)入和常見報錯Doris的導(dǎo)入能力很強但用不好也會讓集群難受。Stream Load是我用得最多的導(dǎo)入方式幾個實操要點label一定要設(shè)計好規(guī)則比如源文件日期加批次號。重復(fù)的label會直接導(dǎo)入失敗這其實是保護機制不是bug。大批量文件建議拆分單個文件超過幾GB時拆成多個文件并行導(dǎo)入不要硬灌一個超大的Stream Load任務(wù)。設(shè)置合理的max_filter_ratio。數(shù)據(jù)質(zhì)量沒把握時允許1%-5%的錯誤比例避免整個批次失敗。但別調(diào)得過大否則臟數(shù)據(jù)混進去會影響統(tǒng)計結(jié)果。常見的導(dǎo)入錯誤里ETL_RUN_FAIL多半是數(shù)據(jù)類型轉(zhuǎn)換不匹配比如字符串字段里混入了非數(shù)字內(nèi)容。COMMIT_FAIL則可能是因為BE在提交階段宕機或網(wǎng)絡(luò)抖動重試時換一個新label即可。5.5 物化視圖在什么時候它真的值得建Doris的物化視圖是我最喜歡的特性之一。它本質(zhì)上是讓Doris自動維護一張預(yù)聚合的表查詢時如果命中物化視圖就直接讀聚合好的數(shù)據(jù)不用重新掃明細。我建物化視圖的原則是固定的高頻聚合查詢才會建不確定的探索性查詢不要建。比如“按天統(tǒng)計各渠道的收入和訂單數(shù)”這種寫死在報表里的指標(biāo)就非常適合CREATE MATERIALIZED VIEW mv_channel_daily AS SELECT dt, channel, SUM(amount), COUNT(order_id) FROM orders GROUP BY dt, channel;建完之后不需要手動管Doris會在導(dǎo)入時自動更新。查詢時如果SQL能自動匹配到這個物化視圖執(zhí)行計劃里會顯示讀取的是物化視圖而不是原始表。需要注意的是物化視圖會消耗額外的存儲和導(dǎo)入計算資源不要建太多每一張都要有明確的業(yè)務(wù)目標(biāo)。5.6 我最后悔沒早點知道的三件事最后分享三條經(jīng)歷半年集群運維后最希望第一天就知道的經(jīng)驗。第一compaction參數(shù)不要頻繁亂調(diào)。新用戶看到Doris里compaction相關(guān)配置容易手癢我一開始也調(diào)過結(jié)果因為cumulative compaction策略改得不合理導(dǎo)入后數(shù)據(jù)遲遲沒有合并查詢變慢?,F(xiàn)在我只保留默認策略只在出現(xiàn)大量小文件時介入。第二BE之間的網(wǎng)絡(luò)質(zhì)量直接影響查詢穩(wěn)定性。Doris跑高并發(fā)查詢時BE節(jié)點之間會有大量shuffle數(shù)據(jù)流。如果某個BE的網(wǎng)卡有丟包或延遲抖動查詢可能整個失敗。生產(chǎn)環(huán)境盡量讓BE在同一個機架或至少同一個可用區(qū)內(nèi)。第三滾動升級前一定看官方Release Notes。Doris的小版本升級通常可以滾動進行一個個替換BE再更新FE但我遇到過某個中間版本的行為變化沒有提前看文檔導(dǎo)致升級后SQL執(zhí)行計劃變了。升級前花半小時讀Release Notes比升級后排查半天問題有價值得多。我現(xiàn)在這套生產(chǎn)環(huán)境的BE已經(jīng)跑了快一年沒有重啟FE經(jīng)歷過兩次滾動升級元數(shù)據(jù)沒有出過問題。如果你也在Presto和Doris之間糾結(jié)我的建議很直接不要看評測文章拿最近的真實SQL和真實數(shù)據(jù)在Doris上做一次完整的POC行不行它自己會告訴你。