動態

詳情 返回 返回

Apache Doris 3.1 正式發佈:半結構化分析全面升級,湖倉一體能力再躍新高 - 動態 詳情

親愛的社區小夥伴們,我們很高興地向大家宣佈,近期我們迎來了 Apache Doris 3.1 版本的正式發佈,歡迎大家下載使用體驗。

3.1 版本是 Apache Doris 在半結構化分析上的一個里程碑版本。在 VARIANT 類型上,3.1 版本新增了稀疏列能力,使得 VARIANT 可以輕鬆應對數萬子列的場景。同時,在 VARIANT 類型上引入了模板化 schema 能力,讓 VARIANT 類型在關鍵路徑上,查詢更快、索引更穩、成本可控,同時不丟失靈活性。在倒排索引能力上,3.1 版本引入了 index v3 版本的索引格式,相比較於 v2 版本存儲空間節省可達 20%。同時,支持了更為豐富的分詞手段,提供了三種全新的分詞器:ICU Tokenizer、IK Tokenizer 和 Basic Tokenizer。還進一步支持了自定義分詞器,可以突破內置分詞器的侷限性,根據業務場景定製,顯著提升搜索召回率。

3.1 版本同樣在湖倉一體上有了顯著的增強。在 3.1 版本中,Apache Doris 將異步物化視圖中的分區構建和透明改寫分區補償,這兩項重要能力引入數據湖中,在湖和倉中間架起一座重要的橋樑。3.1 版本還擴充了對 iceberg 和 paimon 特性的支持範圍。另外,通過引入動態分區裁剪和批量分片執行在特定場景下提升了數據湖查詢的性能多達 40%,並顯著降低了 FE 的內存佔用。同時 3.1 版本還重構了各個數據源的連接屬性,不僅能夠以更加清晰的方式對接各類元數據服務和數據存儲系統,同時還支持了更加豐富的連接能力。

3.1 版本 Apache Doris 持續打磨存儲引擎。提供了全新的數據更新方式 —— 靈活列更新。在部分列更新的基礎上,進一步放開限制。在一次導入中對於每一行可以更新不同的列。另外,在存算分離場景下,優化了 MOW 表部分鏈路的鎖獲取邏輯和使用範圍,提升高併發導入場景的使用體驗。

在性能方面,3.1 着重優化了分區裁剪的能力和規劃性能。在數萬分區和複雜分區過濾表達式的場景下,能夠顯著提升查詢性能並降低資源消耗。同時,3.1 還在優化器中全面引入了基於數據特徵的優化手段,在特定場景下可以獲得超過 10 倍的性能提升。

在 3.1 版本的研發過程中,有超過 90 名貢獻者為 Apache Doris 提交了 1000+ 個優化與修復。 在此向所有參與版本研發、測試和需求反饋的貢獻者們表示最衷心的感謝。

  • GitHub 下載
  • 官網下載

一、VARIANT 半結構化查詢華麗變身

存儲能力質變:稀疏列與子列 Vertical Compaction,輕鬆支持數萬子列

傳統 OLAP 面對“超寬表/超多列”(上千到上萬)常遇到元數據膨脹、合併放大與查詢退化;Doris 3.1 通過 VARIANT 的稀疏子列與子列級 Vertical Compaction,將可維護的列數上限抬升到數萬級。

通過對存儲層的深入優化,Variant 給用户帶來以下收益:

  • 穩定支撐“上千 - 數萬”子列(列式存儲),查詢/合併延遲更平滑。
  • 元數據與索引可控,避免指數級膨脹。
  • 實測可進行 10,000+ 子列提取(列式存儲),Compaction 效率順暢。

超多列的適用場景:

  • 車聯網/IoT 遙測:設備型號多、傳感器維度動態增減。
  • 營銷自動化/CRM:事件/用户屬性持續擴展(如自定義 event/property)。
  • 廣告/埋點事件:海量可選 properties,字段稀疏且不斷演進。
  • 安全審計/日誌:不同源日誌字段各異,需按模式聚合檢索。
  • 電商商品屬性:類目跨度大,商品屬性高度可變。

實現原理

  • 稀疏子列(Sparse Subcolumns):按 JSON Key 頻次排序,只提取 Top-N 高頻子列入“真列式”;長尾保持在稀疏列存儲,避免無序擴張。
  • 子列級 Vertical Compaction:對 VARIANT 子列應用 Vertical Compaction,分組合並、內存佔用更小;合併時動態識別並固化熱點路徑,進一步降低合併開銷。
  • 優化值填充默認值效率,按 batch 的方式進行批量填充(減少虛函數開銷)。
  • 通過 LRU 機制減少內存中列存儲相關元數據緩存內存開銷。

如何開啓與使用

新增列級別控制 Variant 參數,列屬性(Properties):

variant_max_subcolumns_count:默認是0,表明不開啓稀疏列能力,設置成特定值後將會提取 Top-N 高頻的 JSON key 作為列式存儲,餘下的列進入稀疏列存儲。

-- Enable sparse subcolumns and cap hot subcolumn count
CREATE TABLE IF NOT EXISTS tbl (
  k BIGINT,
  v VARIANT<
      properties("variant_max_subcolumns_count" = "2048") -- pick top-2048 hot keys
  >
) DUPLICATE KEY(k);

模板化 Schema(Schema Template) - 變化中的不變量

一句話總結:模板化 Schema 讓“常變”的 JSON 在關鍵路徑上“變得可預期”:查詢更快、索引更穩、成本可控,同時不丟失靈活性。

使用模板化的 Schema,將會給使用 Variant 數據類型帶來以下收益:

  • 類型穩定:關鍵子路徑類型可在 DDL 中固定,避免類型漂移引發的查詢報錯、索引失效與隱式轉換開銷。
  • 檢索更快更準:為不同子路徑定製倒排策略(分詞/非分詞、解析器、短語搜索等),常用查詢延遲更低、命中更穩定。
  • 索引與成本可控:不再“整列統一繼承索引”(2.1 的做法易膨脹),而是“按子路徑精細化配置”,顯著降低索引數量、寫放大與存儲成本。
  • 可維護/可協作:等同給 JSON 加“數據契約”,跨團隊語義一致;類型與索引狀態更可觀測,問題更易定位。
  • 演進友好:核心高頻路徑模板化並可選建索引,長尾字段繼續保持靈活擴展,不犧牲可擴展性。

如何開啓與使用

  • 顯式聲明結構,指定類型:在VARIANT<...>中預定義常用子路徑與類型(含通配),例如'a' : int, 'c.d' : text, 'array_int_*' : array<int>
  • 配置索引,針對同一 VARIANT 列的不同子路徑配置不同索引策略(field_pattern、解析器、分詞、短語搜索等),差異化提升檢索效率,可用通配符批量匹配。
  • 新增列級別控制 Variant 參數,列屬性(Properties):variant_enable_typed_paths_to_sparse:默認是false,表明預定義的列不會進入稀疏列, true 開啓後預定義類型路徑也會進入稀疏存儲(用於避免匹配過多列後導致的列數膨脹)

示例 1:schema 定義 + 單列多索引

-- Common properties: field_pattern (target subpath), analyzer, parser, support_phrase, etc.
CREATE TABLE IF NOT EXISTS tbl (
    k BIGINT,
    v VARIANT<'content' : STRING>, -- specify concrete type for subcolumn 'content'
    INDEX idx_tokenized(v) USING INVERTED PROPERTIES("parser" = "english", "field_pattern" = "content"), -- tokenized inverted index for 'content' with english parser
    INDEX idx_v(v) USING INVERTED PROPERTIES("field_pattern" = "content") -- non-tokenized inverted index for 'content'
);

-- v.content will have both a tokenized (english) inverted index and a non-tokenized inverted index

-- Use tokenized index
SELECT * FROM tbl WHERE v['content'] MATCH 'Doris';

-- Use non-tokenized index
SELECT * FROM tbl WHERE v['content'] = 'Doris';

示例 2:通配符批量處理符合模式的列

-- Use wildcard-typed subpaths with per-pattern indexes
CREATE TABLE IF NOT EXISTS tbl2 (
  k BIGINT,
  v VARIANT<
      'pattern1_*' : STRING, -- batch-typing: all subpaths matching pattern1_* are STRING
      'pattern2_*' : BIGINT, -- batch-typing: all subpaths matching pattern2_* are BIGINT
      properties("variant_max_subcolumns_count" = "2048") -- enable sparse subcolumns; keep top-2048 hot keys
  >,
  INDEX idx_p1 (v) USING INVERTED
    PROPERTIES("field_pattern"="pattern1_*", "parser" = "english"), -- tokenized inverted index for pattern1_* with english parser
  INDEX idx_p2 (v) USING INVERTED
    PROPERTIES("field_pattern"="pattern2_*") -- non-tokenized inverted index for pattern2_*
) DUPLICATE KEY(k);

示例 3:允許預定義類型的列進入稀疏列

-- Allow predefined typed paths to participate in sparse extraction
CREATE TABLE IF NOT EXISTS tbl3 (
  k BIGINT,
  v VARIANT<
    'message*' : STRING, -- batch-typing: all subpaths matching prefix 'message*' are STRING
    properties(
      "variant_max_subcolumns_count" = "2048",              -- enable sparse subcolumns; keep top-2048 hot keys
      "variant_enable_typed_paths_to_sparse" = "true"       -- include typed (predefined) paths as sparse candidates (default: false)
    )
  >
) DUPLICATE KEY(k);

二、索引架構全面進化

倒排索引存儲格式 V3 - 性能和功能的雙重提升

相比 V2 進一步優化存儲

索引文件更小,減少磁盤佔用和 I/O 開銷,以 httplogs 與 logsbench 兩個測試集測試結果來看,存儲空間最大可以通過 V3 節省 20%,適合大規模文本數據、日誌分析場景。

index-optimization-1.PNG

核心改進

  • 引入倒排索引 ZSTD 詞典壓縮:採用 ZSTD 壓縮算法對倒排索引內的詞典文件進行壓縮,通過 index properties 中的 dict_compression 開啓。
  • 新增倒排索引位置信息壓縮:支持對倒排索引中為每個 term 即詞元記錄的位置信息進行編碼壓縮,進一步減少倒排索引空間佔用。

使用方式

-- 建表時啓用V3格式
CREATE TABLE example_table (
    content TEXT,
    INDEX content_idx (content) USING INVERTED
    PROPERTIES("parser" = "english", "dict_compression" = "true")
) ENGINE=OLAP
PROPERTIES ("inverted_index_storage_format" = "V3");

倒排索引 - 分詞器靈活多樣好用易用

新增三種常用分詞器

進一步提升用户在不同場景下的分詞需求:

ICU Tokenizer

  • 實現:ICU(International Components for Unicode)
  • 適用場景:包含複雜文字系統的國際化文本,特別適合多語言混合文檔。
  • 示例

    SELECT TOKENIZE('مرحبا بالعالم Hello 世界', '"parser"="icu"');
    -- 結果:["مرحبا", "بالعالم", "Hello", "世界"]
    
    SELECT TOKENIZE('มนไมเปนไปตามความตองการ', '"parser"="icu"');
    -- 結果:["มน", "ไมเปน", "ไป", "ตาม", "ความ", "ตองการ"]

IK Tokenizer

  • 實現:IK Analyzer(中文分詞器),基於算法的高級中文分詞,結合詞典和統計模型
  • 適用場景:對分詞質量要求較高的中文文本處理
  • 模式

    • ik_smart:智能模式,詞少且更長,語義集中,適合精確搜索
    • ik_max_word:最細粒度模式,更多短詞,覆蓋更全面,適合召回搜索
  • 示例

    -- 智能模式
    SELECT TOKENIZE('中華人民共和國國歌', '"parser"="ik","parser_mode"="ik_smart"');
    -- 結果:["中華人民共和國", "國歌"]
    
    -- 最細粒度模式
    SELECT TOKENIZE('中華人民共和國國歌', '"parser"="ik","parser_mode"="ik_max_word"');
    -- 結果:["中華人民共和國", "中華人民", "中華", "華人", "人民共和國", "人民", "共和國", "共和", "國歌"]

Basic Tokenizer

  • 實現:簡單規則的自定義分詞器,基礎分詞,採用字符類型識別進行分詞
  • 適用場景:簡單場景、對性能要求極高的場景
  • 分詞規則

    • 連續的字母數字字符作為一個詞(word tokens)
    • 中文字符單獨分詞(每個漢字一個 token)
    • 忽略標點符號、空格和特殊符號
  • 示例

    -- 英文文本分詞
    SELECT TOKENIZE('Hello World! This is a test.', '"parser"="basic"');
    -- 結果:["hello", "world", "this", "is", "a", "test"]
    
    -- 中文文本分詞
    SELECT TOKENIZE('你好世界', '"parser"="basic"');
    -- 結果:["你", "好", "世", "界"]
    
    -- 混合語言分詞
    SELECT TOKENIZE('Hello 你好 World 世界', '"parser"="basic"');
    -- 結果:["hello", "你", "好", "world", "世", "界"]
    
    -- 包含數字和特殊字符
    SELECT TOKENIZE('GET /images/hm_bg.jpg HTTP/1.0', '"parser"="basic"');
    -- 結果:["get", "images", "hm", "bg", "jpg", "http", "1", "0"]
    
    -- 處理長數字序列
    SELECT TOKENIZE('12345678901234567890', '"parser"="basic"');
    -- 結果:["12345678901234567890"]

自定義分詞

推出自定義分詞功能,方便用户根據自身分詞需求,進行 DIY 組合,進一步提高文本檢索召回率。自定義分詞可以突破內置分詞的侷限,根據特定需求組合字符過濾器、分詞器和詞元過濾器,精細定義文本如何被切分成可搜索的詞項,這直接決定了搜索結果的相關性與數據分析的準確性。

index-optimization-2.PNG

使用場景舉例

  • 問題

使用默認 unicode 分詞器時,電話號碼"13891972631"被當作完整 token,無法支持前綴搜索如"138"。

  • 解決方案

    • 創建分詞器(tokenizer)
    • 使用 Edge N-gram 自定義分詞器:

       CREATE INVERTED INDEX TOKENIZER IF NOT EXISTS edge_ngram_phone_tokenizer
        PROPERTIES
        (
            "type" = "edge_ngram",
            "min_gram" = "3",
            "max_gram" = "10",
            "token_chars" = "digit"
        );
  • 創建分析器(analyzer)
  CREATE INVERTED INDEX ANALYZER IF NOT EXISTS phone_prefix_analyzer
    PROPERTIES
    (
        "tokenizer" = "edge_ngram_phone_tokenizer"
    );
  • 創建表指定 analyzer

    CREATE TABLE customer_contacts (
    id bigint NOT NULL AUTO_INCREMENT(1),
    phone text NULL,
    INDEX idx_phone (phone) USING INVERTED PROPERTIES(
        "analyzer" = "phone_prefix_analyzer"
    )
    ) ENGINE=OLAP
    DUPLICATE KEY(id)
    DISTRIBUTED BY RANDOM BUCKETS 1
    PROPERTIES ("replication_allocation" = "tag.location.default: 1");
  • 查看分詞效果

    SELECT tokenize('13891972631', '"analyzer"="phone_prefix_analyzer"');
    +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | tokenize('13891972631', '"analyzer"="phone_prefix_analyzer"')                                                                                                                                                                                                                                |
    +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | [{
          "token": "138"
      }, {
          "token": "1389"
      }, {
          "token": "13891"
      }, {
          "token": "138919"
      }, {
          "token": "1389197"
      }, {
          "token": "13891972"
      }, {
          "token": "138919726"
      }, {
          "token": "1389197263"
      }] |
    +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
  • 文本搜索效果

    SELECT * FROM customer_contacts_optimized WHERE phone MATCH '138';
    +------+-------------+
    | id   | phone       |
    +------+-------------+
    |    1 | 13891972631 |
    |    2 | 13812345678 |
    +------+-------------+
    SELECT * FROM customer_contacts_optimized WHERE phone MATCH '1389';
    +------+-------------+
    | id   | phone       |
    +------+-------------+
    |    1 | 13891972631 |
    |    2 | 13812345678 |
    +------+-------------+
    2 rows in set (0.043 sec)

通過 Edge N-gram 分詞器,一個電話號碼被拆分成多個前綴 token,實現了靈活的前綴匹配搜索。

三、湖倉一體能力再躍新高

異步物化視圖全面支持數據湖

在 3.1 版本中,異步物化視圖再次進化,現在可以完整支持 Paimon / Iceberg / Hudi 的分區增量構建和分區透明改寫。Doris 自 2.1 版本支持異步物化視圖功能開始。經過多個版本的迭代。已經支持了非常多有價值的特性。包括:

lakehouse.PNG

3.1 版本則重點打磨湖倉一體方向上的功能,全面支持主流的數據湖表格式 Paimon / Iceberg / Hudi 的分區刷新,和透明改寫時的外部數據源分區補償。使其成為聯通湖和倉之間的高速公路。具體支持範圍詳見下表:

lakehouse-2.PNG

Iceberg / Paimon 能力全面擴充

Iceberg

3.1.0 版本針對 Iceberg 表格式上做出多項優化和能力增強,緊密推進與 Iceberg 最新特性的融合。

支持 Branch / Tag 完整生命週期管理

從 3.1.0 開始,Doris 原生支持 Iceberg Branch & Tag 的創建、刪除、讀取與寫入操作。該功能能夠讓用户像 Git 一樣操作和管理 Iceberg 表數據。這一能力為 Iceberg 表格式的多版本並行管理、灰度測試、環境隔離等業務場景提供了原生的支持,無需額外引擎或自定義邏輯。

-- 創建分支
ALTER TABLE iceberg_tbl CREATE BRANCH b1;
-- 寫入數據到指定分支
INSERT INTO iceberg_tbl@branch(b1) values(1, 2);
-- 查詢指定分支
SELECT * FROM iceberg_tbl@branch(b1);

豐富的 Iceberg 系統表支持

3.1.0 新增對 Iceberg $entries$files$history$manifests$refs$snapshots 等系統表的支持,可用 SELECT * FROM iceberg_table$history…$refs 等語句直接查詢 Iceberg 的底層 metadata、snapshot 列表、分支/標籤信息等,從而深入瞭解數據文件的組織結構、快照的變更歷史以及分支的映射情況。這種能力大大提升了 Iceberg 元數據的可觀測性,使得問題定位、調優分析和治理決策更加直觀、透明。

如通過系統表查看 delete file 數量:

SELECT
  CASE
    WHEN content = 0 THEN 'DataFile'
    WHEN content = 1 THEN 'PositionDeleteFile'
    WHEN content = 2 THEN 'EqualityDeleteFile'
    ELSE 'Unknown'
  END AS ContentType,
  COUNT(*) AS FileNum,
  SUM(file_size_in_bytes) AS SizeInBytes,
  SUM(record_count) AS Records
FROM
  iceberg_table$files
GROUP BY
  ContentType;

+--------------------+---------+-------------+---------+
| ContentType        | FileNum | SizeInBytes | Records |
+--------------------+---------+-------------+---------+
| EqualityDeleteFile |    2787 |     1432518 |   27870 |
| DataFile           |    2787 |     4062416 |   38760 |
| PositionDeleteFile |      11 |       36608 |   10890 |
+--------------------+---------+-------------+---------+

Iceberg 視圖查詢

3.1.0 版本新增對 Iceberg 邏輯視圖的訪問和查詢。該功能進一步提升了 Doris 對 Iceberg 功能的完善程度。在後續 3 位版本迭代中,我們將進一步支持 Iceberg View 的 SQL 方言轉換能力。

通過 ALTER 語句修改 Iceberg 表結構

3.1.0 支持通過 ALTER TABLE 語句對 Iceberg 表進行字段的新增、刪除、重命名和重排序操作。該功能進一步完善了 Doris 對 Iceberg 表的管理能力,無需再借助 Spark 等第三方引擎進行 Iceberg 表管理。

ALTER TABLE iceberg_table
ADD COLUMN new_col int;

同時,在 3.1.0 版本中,Iceberg 的依賴版本升級到 1.9.2,以便更好的支持 Iceberg 的新的功能。在後續 3.1 的迭代版本中,我們將進一步增強 Iceberg 的表管理能力,包括數據合併、分支演進等能力。

詳情參考文檔

Paimon

3.1.0 版本針對 Paimon 表格式,結合用户實際場景,進行了多項功能更新和能力增強。

支持 Paimon Batch Incremental Query

3.1.0 版本支持讀取 Paimon 表指定的兩個快照之間的增量數據。該功能增強了用户對 Paimon 表增量數據的訪問能力。尤其是在增量物化視圖構建方面,基於此功能實現了 Paimon 表的增量聚合物化視圖能力。詳見物化視圖方面的説明。

SELECT * FROM paimon_tbl@incr('startSnapshotId'='2', 'endSnapshotId'='5');

支持 Branch / Tag 讀取

從 3.1.0 開始,Doris 支持對 Paimon 表的 Branch / Tag 進行讀取,幫助用户更靈活的訪問多版本的 Paimon 數據。

SELECT * FROM paimon_tbl@branch(branch1);
SELECT * FROM paimon_tbl@tag(tag1);

豐富的 Paimon 系統表支持

同 Iceberg 一樣,3.1.0 新增對 Paimon $files$partitions$manifests$tags$snapshots 等系統表的支持,可用 SELECT * FROM partition_table$files 等語句直接查詢 Paimon 的底層元數據信息。更方便用户對 Paimon 表進行探測、調試和優化。

如我們可以通過系統表統計分區新增數據文件:

SELECT
  partition,
  COUNT(*) AS new_file_count,
  SUM(file_size_in_bytes)/1024/1024 AS new_total_size_mb
FROM my_table$files
WHERE creation_time >= DATE_SUB(NOW(), INTERVAL 3 DAY)
GROUP BY partition
ORDER BY new_total_size_mb DESC;

在 3.1.0 版本中,Paimon 的依賴版本升級到 1.1.1,以便更好的支持 Paimon 的新的功能。

詳情參考文檔

數據湖查詢性能更上一層樓

3.1.0 版本,針對數據湖表格式的查詢性能進行了多項深度優化,旨在實際生產環境下,為用户提供更加穩定、高效的數據湖分析能力。

動態分區裁剪

動態分區裁剪功能,能夠在多表關聯查詢場景下,根據右表數據生成分區列謂詞,並對左表數據進行運行時的分區剪枝,從而減少數據 IO,提升查詢性能。在 3.0 版本中,Doris 已經支持了 Hive 表的動態分區裁剪功能。在 3.1.0 版本中,這個功能進一步擴充到了 Iceberg、Paimon 和 Hudi 表上。在測試場景下,針對選擇率較高的查詢,可以提升 30%-40% 的性能。

批量分片執行

當湖表的數據分片較多時,如果 FE 進行規劃並將所有分片信息一次性組裝完成發送給 BE,那麼可能造成 FE 內存消耗過大以及處理實際過長的問題。尤其是在查詢大數據量表時,會導致規劃部分的資源開銷大耗時長。批量分片執行功能,通過分批次生產數據分片信息,並且邊生產變執行,能夠有效緩解 FE 的內存開銷,同時能夠讓分片信息的生產和執行並行執行,提升整體的執行效率。在 3.0 版本中,Doris 已經支持了 Hive 表上的該功能。在 3.1.0 版本中,進一步增加了對 Iceberg 表的批量分片執行支持。在大數據量測試場景下,可以顯著降低 FE 的內存開銷和查詢規劃時間。

聯邦分析 - 連接器更好用更多樣

3.1 版本重構了各個數據源的連接屬性,不僅能夠以更加清晰的方式對接各類元數據服務和數據存儲系統,同時還支持了更加豐富的連接能力。

Iceberg Rest Catalog

3.1 版本進一步增強了對 Iceberg Rest Catalog 的支持。不僅支持了包括 Unity、Polaris、Gravitino、Glue 等多種 Iceberg Rest Catalog 後端實現,同時支持了 vended credentials 功能,能夠更加安全、靈活的管理訪問憑證。目前支持 AWS 平台,後續小版本迭代中將陸續支持 GCP、Azure 等雲平台的憑證管理。

詳情參考文檔

支持 Paimon Rest Catalog

3.1.0 版本中支持基於阿里雲 DLF 的 Paimon Rest Catalog,可以直接訪問新版本 DLF 管理的 Paimon 表數據。

詳情參考文檔

多 Kerberos 環境支持

3.1 版本允許用户在同一個 Doris 集羣內訪問不同的 Kerberos 認證環境。不同的 Kerberos 環境可能採用不同的 KDC 服務、Principal 以及對應的 Keytab。新版本允許針對不同的 Catalog,配置不同的 Kerberos 認證信息,並且相互之間不受干擾。該功能極大的方便了擁有多套 Kerberos 認證環境的用户,可以使用 Doris 進行統一的訪問管理。

詳情參考文檔

多 Hadoop 環境支持

在之前的版本中,Doris 只允許用户在 conf 目錄下放置一套 hadoop 集羣的配置文件(hive-site.xml,hdfs-site.xml 等)。如果用户有多套不同的 Hadoop 環境和配置,則無法支持。新版本運行用户為不同的 Catalog 指定不同的 Hadoop 配置文件,幫助用户更靈活的管理外部數據源。

詳情參考文檔

四、存儲層構持續打磨

在 3.1 版本中,我們對存儲層也進行了持續的打磨,性能和穩定性都有了顯著的提升。

靈活列更新 - 數據更新全新體驗

此前 Doris 的部分列更新功能要求一次導入中每一行必須更新相同的列。在一些場景下,源端系統輸出的記錄往往只包含主鍵和被更新的列,不同行更新的列可能不同。為了解決這種需求,Doris 引入了 靈活列更新 功能,使用靈活列更新可以大幅簡化用户側按列攢數據的工作以及提升寫入性能。

使用方式

  • 創建 Merge-on-Write Unique 表 時,在表屬性中開啓:
  • "enable_unique_key_skip_bitmap_column" = "true"
  • 在導入時指定導入模式:
  • unique_key_update_mode: UPDATE_FLEXIBLE_COLUMNS
  • Doris 會自動完成靈活列更新與數據補齊。

示例 支持在一次導入中對不同記錄更新不同的列,例如:

  • 刪除某行(DORIS_DELETE_SIGN
  • 更新部分列(如 v1v2v5 等)
  • 插入新行(僅提供主鍵和被更新列,其他列使用默認值或補齊歷史值)

效果

  • 在測試環境下(1 FE + 4 BE,16C 64GB,3 億行 101 列數據,3 副本行存表):

    • 每次導入 20,000 行,僅更新 1 列(需補齊 99 列)
    • 單併發導入性能可達 10.4k 行/s
    • 單機資源佔用:CPU ~60%,內存 ~30GB,讀 IOPS ~7.5k/s,寫 IOPS ~5k/s

存算分離 mow 鎖優化

在存算分離場景下,MOW 表更新 Delete Bitmap 需要獲取分佈式鎖 delete_bitmap_update_lock。原有實現中,導入、Compaction 和 Schema Change 會競爭該鎖,容易在高併發導入場景下導致長時間等待甚至失敗。

本次優化包括兩方面:

減少 Compaction 持鎖時間

  • 通過引入新的 mow_tablet_compaction_key,避免多個 Compaction/Schema Change 任務在更新 initiators 列表時產生不必要的事務衝突。
  • 在多 Tablet 高併發導入測試中,導入提交事務的 p99 平均耗時從 1.68 分鐘降低到 49.4 秒,大幅降低了事務提交延遲。
  • 新增配置項 delete_bitmap_lock_v2_white_list,支持為指定倉庫開啓該優化。

降低導入事務長尾延遲

  • 增加 FE 配置 mow_load_force_take_ms_lock_threshold_ms,當導入事務等待鎖超過閾值時,將強制獲取分佈式鎖,避免長時間飢餓。
  • 在高併發導入測試下,該優化顯著減少了導入事務的長尾延遲。

五、查詢性能提升

分區裁剪性能和適用範圍提升

Doris 支持數據按照分區組織,這些分區可以獨立存儲、獨立查詢、獨立管理。通過分區,可以提升查詢性能、優化數據管理,並降低資源消耗。在查詢過程中,通過使用過濾條件,提前過濾無需查詢的分區,可以顯著提升查詢性能,降低系統資源消耗。在日誌數據分析系統,風控系統等使用場景中,單表可能存在萬級別甚至十萬級別的分區數量,而通常單詞查詢,只會命中百級別以下的分區數據。對於在這類數據上的查詢,能否分區裁剪,對於查詢性能的影響十分顯著。

在 3.1 版本中,Doris 通過引入一系列的優化,顯著提升了分區裁剪的性能和適用範圍,包括

  • 分區裁剪二分查找。對於在時間列上的分區,通過將分區按照列值排序,將分區裁剪的計算從線性遍歷,改為二分查找。在使用 DATETIME 類型作為分區字段,13.6 萬分區數的場景下。實測分區裁剪的耗時,從 724ms 提升到 43ms。提升超過 16 倍。
  • 增加大量單調函數參與分區裁剪。在實際的使用場景中,在時間分區列上的過濾條件,通常不是簡單的邏輯比較,而是在分區列上包含時間函數計算的複雜表達式。如:to_date(time_stamp) > '2022-12-22',date_format(timestamp,'%Y-%m-%d %H:%i:%s') > '2022-12-22 11:00:00'等。Doris 在 3.1 版本中引入了函數單調特性描述,當函數為單調函數時,可以通過計算分區邊界值是否可以被裁剪得知整個分區是否可以被裁剪。在 3.1 版本中,已經支持了 CAST 和 25 個常見的時間相關的函數。可以覆蓋絕大多數常見的時間類型分區列上的過濾條件。
  • 此外,3.1 版本中,還對分區裁剪的全路徑代碼做了許多代碼級別的詳細優化,減少了不必要開銷。

洞察數據特徵 - 獲得性能 10 倍的潛力

在 3.1 中,優化器可以更聰明的使用數據特徵對查詢進行優化。優化器會執行計劃樹種各個節點的收集唯一性(Unique)、均一性(Uniform),等值集(Equal Set)等數據特徵,並推導列之間的函數依賴關係。當在特定的節點,數據符合特定特徵時,可以移除不必要的連接、聚合或排序計算,顯著提升查詢性能。

在針對特定優化構建的測試用例下,利用數據特徵可以獲得超過 10 倍的性能提升,詳見下表:

query-performance.PNG

六、功能改進

半結構化

VARIANT

  • 新增 variant_type(x)函數:返回 Variant 子 field 對應的“當前實際類型”。
  • 新增 ComputeSignature/Helper,增強函數參數/返回類型推斷能力。

STRUCT

  • 支持使用 Schema Change 為 STRUCT 類型增加子列

湖倉一體

  • 支持在 Catalog 級別設置元數據緩存策略,如緩存過期時間等。幫助用户根據需求靈活調整數據時效性和元數據訪問性能。詳情參考文檔
  • 支持 FILE() 表函數(Table Valued Function),該表函數是原有的 S3()HDFS()LOCAL()表函數的集合,方便用户使用和理解。

聚合算子能力增強

在 3.1 版本中,優化器重點增強了聚合算子。支持了兩個使用較為廣泛的能力。

非標 GROUP BY 支持

對於標準的聚合查詢,要求聚合輸出的標量表達式,其本身或其子樹必須是聚合鍵。但在 MySQL 中,當設置了 SQL_MODE 不包含 "ONLY_FULL_GROUP_BY" 時,則沒有次限制。詳見 MySQL 文檔

此時,此列輸出的值為聚合鍵對應多行中的任意一行計算的值。舉例如下:

-- 非標 GROUP BY
SELECT c1, c2 FROM t GROUP BY c1
-- 等價於
SELECT c1, any_value(c2) FROM t GROUP BY c1

在 3.1 版本中。Doris 在 SQL_MODE 中默認開啓 "ONLY_FULL_GROUP_BY" ,即和之前的行為保持一致。如果需要使用非標 GROUP BY 功能。則可以通過如下設置開啓:

set sql_mode = replace(@@sql_mode, 'ONLY_FULL_GROUP_BY', '');

多 distinct 聚合支持

在之前的版本中,如果聚合查詢中,包含多個 distinct 聚合函數,且他們的參數不一致。同時聚合函數的 distinct 語義和非 distinct 語義不一致,且不是以下之一,則 Doris 無法執行查詢:

  • 單參數的 COUNT
  • SUM
  • AVG
  • GROUP_CONCAT

在 3.1 版本中,Doris 對此方面進行了加強。現在這些查詢可以正常執行並獲取結果。例如:

SELECT count(DISTINCT c1,c2), count(DISTINCT c2,c3), count(DISTINCT c3) FROM t;

連接協議增強

  • 開啓 Proxy Protocol 協議後,依然可以通過非該協議的客户端連接。該改進在負載均衡 IP 透傳場景下,方便用户更靈活的連接 Doris。
  • 查詢 VIEW 時,JDBC 的元數據接口 ResultSetMetaData#getColumnName 可以正確的返回 VIEW 中的列名

七、行為變更

VARIANT

  • variant_max_subcolumns_count 約束

    • 同一張表中,所有 Variant 列的 variant_max_subcolumns_count 必須“要麼全為 0,要麼全為 > 0”。混用會在建表 / Schema Change 時報錯。
  • 新的 Variant 讀寫/serde 與 Compaction 路徑對舊數據兼容。老版本 Variant 升級上來查詢格式會產生差異(比如多一些空格、或是分隔符導致層級構建,產生額外的層級)
  • 創建 Variant 倒排索引,如果數據中所有字段不符合索引條件也會生成空索引文件,屬預期行為

權限

  • show transcation 的權限需求從擁有 ADMIN_PRIV 權限,變更為擁有導入對應數據庫的 LOAD_PRIV 權限
  • 統一了 SHOW FRONTENDS / BACKENDS 和 NODE Restful API 的權限。現在這些接口的權限需求為擁有 information_schema 庫的 SELECT_PRIV 權限。

立刻開啓 3.1

在 3.1 版本正式發佈之前,半結構化和數據湖的多個能力已經經過真實線上場景的驗證,並獲得了符合預期的性能提升。推薦有相應能力需求的用户下載嚐鮮。

致謝

在此,再次向所有參與版本研發、測試和需求反饋的貢獻者們表示最衷心的感謝:

@924060929 @airborne12 @amorynan @BePPPower @BiteTheDDDDt @bobhan1 @CalvinKirs @cambyzju @cjj2010 @csun5285 @DarvenDuan @dataroaring @deardeng @dtkavin @dwdwqfwe @eldenmoon @englefly @feifeifeimoon @feiniaofeiafei @felixwluo @freemandealer @Gabriel39 @gavinchou @ghkang98 @gnehil @gohalo @HappenLee @heguanhui @hello-stephen @HonestManXin @htyoung @hubgeter @hust-hhb @jacktengg @jeffreys-cat @Jibing-Li @JNSimba @kaijchen @kaka11chen @KeeProMise @koarz @liaoxin01 @liujiwen-up @liutang123 @luwei16 @MoanasDaddyXu @morningman @morrySnow @mrhhsg @Mryange @mymeiyi @nsivarajan @qidaye @qzsee @Ryan19929 @seawinde @shuke987 @sollhui @starocean999 @suxiaogang223 @SWJTU-ZhangLei @TangSiyang2001 @Vallishp @vinlee19 @w41ter @wangbo @wenzhenghu @wumeibanfa @wuwenchi @wyxxxcat @xiedeyantu @xinyiZzz @XLPE @XnY-wei @XueYuhai @xy720 @yagagagaga @Yao-MR @yiguolei @yoock @yujun777 @Yukang-Lian @Yulei-Yang @yx-keith @Z-SWEI @zclllyybb @zddr @zfr9527 @zgxme @zhangm365 @zhangstar333 @zhaorongsheng @zhiqiang-hhhh @zy-kkk @zzzxl1993

user avatar zhidechaomian_detxs7 頭像 ting_61d6d9790dee8 頭像 u_17397181 頭像 mianlengxincidehongjiu 頭像 rivers_chaitin 頭像 nocobase 頭像 apacheiotdb 頭像 tdengine 頭像 quanzhikeji 頭像 iex365 頭像 tangpanqing 頭像 openbuild 頭像
點贊 23 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.