點擊關注,瞭解更多實時數倉領域前沿資訊與技術實踐!
親愛的社區小夥伴們,我們很高興地向大家宣佈,近期我們迎來了 Apache Doris 4.0 版本的正式發佈,歡迎大家下載使用體驗。
本次發佈圍繞 “AI 驅動、搜索增強、離線提效” 三大核心方向,新增向量索引、AI 函數等關鍵特性,完善搜索功能矩陣,優化離線計算穩定性與資源利用率,並通過多項底層改進提升查詢性能與數據質量,為用户構建更高效、更靈活的企業級數據分析平台。
在 4.0 版本的研發過程中,有超過 200 名貢獻者為 Apache Doris 提交了 9000+ 個優化與修復。 在此向所有參與版本研發、測試和需求反饋的貢獻者們表示最衷心的感謝。
- GitHub 下載:https://github.com/apache/doris/releases
- 官網下載:https://doris.apache.org/download
一、AI 能力深度集成,開啓智能分析新範式
隨着大模型與向量檢索技術在企業級場景的加速落地與深度滲透,本次 Doris 版本迭代將重點強化 AI 原生支持能力。通過向量索引技術,高效融合企業的結構化與非結構化數據,Doris 將突破傳統數據庫的功能邊界,直接升級為企業核心的 “AI 分析中樞”,為業務端的智能化決策與創新實踐提供穩定、高效的底層數據支撐。
01 向量索引(Vector Index)
正式引入向量索引功能,支持對高維向量數據(如文本嵌入、圖像特徵等)進行高效存儲與檢索。結合 Doris 原生的 SQL 分析能力,用户可直接在數據庫內完成 “結構化數據查詢 + 向量相似性搜索” 的一體化分析,無需跨系統整合,大幅降低 AI 應用(如智能推薦、語義搜索、圖像檢索)的開發與部署成本。
向量索引檢索函數介紹
l2_distance_approximate()使用 HNSW 索引按 歐氏距離(L2) 近似計算相似度。數值越小越相似。inner_product_approximate()使用 HNSW 索引按 內積(Inner Product) 近似計算相似度。數值越大越相似。
示例
-- 1) 建表與索引
CREATE TABLE doc_store (
id BIGINT,
title STRING,
tags ARRAY<STRING>,
embedding ARRAY<FLOAT> NOT NULL,
INDEX idx_vec (embedding) USING ANN PROPERTIES (
"index_type" = "hnsw",
"metric_type" = "l2_distance",
"dim" = "768",
"quantizer" = "flat" -- 可選:flat / sq8 / sq4
),
INDEX idx_title (title) USING INVERTED PROPERTIES ("parser" = "english")
)
DUPLICATE KEY(id)
DISTRIBUTED BY HASH(id) BUCKETS 16
PROPERTIES("replication_num"="1");
-- 2) TopN 最近鄰(建議使用 PreparedStatement 傳入向量), 用真實向量替換下面的 ... 佔位符
SELECT id, l2_distance_approximate(embedding, [...]) AS dist
FROM doc_store
ORDER BY dist ASC
LIMIT 10;
-- 3) 帶過濾條件的 ANN(先過濾後TopN,保障召回), 用真實向量替換下面的 ... 佔位符
SELECT id, title,
l2_distance_approximate(embedding, [...]) AS dist
FROM doc_store
WHERE title MATCH_ANY 'music' -- 使用倒排索引快速過濾
AND array_contains(tags, 'recommendation') -- 結構化過濾
ORDER BY dist ASC
LIMIT 5;
-- 4) 範圍查詢,, 用真實向量替換下面的 ... 佔位符
SELECT COUNT(*)
FROM doc_store
WHERE l2_distance_approximate(embedding, [...]) <= 0.35;
建索引參數
index_type:必填,當前支持hnsw。metric_type:必填,l2_distance/inner_product。dim:必填,正整數,需與導入向量維度嚴格一致。max_degree:可選,默認 32;控制 HNSW 圖節點出度(M)。ef_construction:可選,默認 40;構建階段候選隊列長度。quant:可選,flat(默認)/sq8/sq4;量化可顯著降低內存佔用,SQ8 索引體積約為 FLAT 的 1/3,以小幅召回損失換取更高容量/更低成本。
注意事項
- Doris 默認採用“前過濾”:先用可精確定位的索引(如倒排)做謂詞過濾,再在剩餘集合上進行 ANN TopN,確保結果可解釋與召回穩定。
- 如 SQL 中出現 無法由二級索引精確定位 的謂詞(例:
ROUND(id) > 100且id無倒排等二級索引),為保證前過濾語義與正確性,系統將 回退精確暴力搜索。 - 向量列需為
ARRAY<FLOAT> NOT NULL,且導入向量維度必須與索引dim一致。 - ANN 目前僅支持 Duplicate Key 表模型。
AI Functions 函數庫
讓數據分析師能夠直接通過簡單的 SQL 語句,調用大語言模型進行文本處理。無論是提取特定重要信息、對評論進行情感分類,還是生成簡短的文本摘要,現在都能在數據庫內部無縫完成:
- AI_CLASSIFY: 在給定的標籤中提取與文本內容匹配度最高的單個標籤字符串。
- AI_EXTRACT: 根據文本內容,為每個給定標籤提取相關信息。
- AI_FILTER: 判斷文本內容是否正確,返回值為 bool 類型。
- AI_FIXGRAMMAR: 修復文本中的語法、拼寫錯誤。
- AI_GENERATE: 基於參數內容生成內容。
- AI_MASK: 根據標籤,將原文中的敏感信息用
[MASKED]進行替換處理。 - AI_SENTIMENT: 分析文本情感傾向,返回值為
positive、negative、neutral、mixed其中之一。 - AI_SIMILARITY: 判斷兩文本的語義相似度,返回值為 0 - 10 之間的浮點數,值越大代表語義越相似。
- AI_SUMMARIZE: 對文本進行高度總結概括。
- AI_TRANSLATE: 將文本翻譯為指定語言。
- AI_AGG: 對多條文本進行跨行聚合分析。
目前支持的大模型包括:OpenAI、Anthropic、Gemini、DeepSeek、Local、MoonShot、MiniMax、Zhipu、Qwen、Baichuan。例如:模擬一個簡歷篩選的需求,通過以下 SQL 在語義層進行篩選。
以下表模擬在招聘時的候選人簡歷和職業要求:
CREATE TABLE candidate_profiles (
candidate_id INT,
name VARCHAR(50),
self_intro VARCHAR(500)
)
DUPLICATE KEY(candidate_id)
DISTRIBUTED BY HASH(candidate_id) BUCKETS 1
PROPERTIES (
"replication_num" = "1"
);
CREATE TABLE job_requirements (
job_id INT,
title VARCHAR(100),
jd_text VARCHAR(500)
)
DUPLICATE KEY(job_id)
DISTRIBUTED BY HASH(job_id) BUCKETS 1
PROPERTIES (
"replication_num" = "1"
);
INSERT INTO candidate_profiles VALUES
(1, 'Alice', 'I am a senior backend engineer with 7 years of experience in Java, Spring Cloud and high-concurrency systems.'),
(2, 'Bob', 'Frontend developer focusing on React, TypeScript and performance optimization for e-commerce sites.'),
(3, 'Cathy', 'Data scientist specializing in NLP, large language models and recommendation systems.');
INSERT INTO job_requirements VALUES
(101, 'Backend Engineer', 'Looking for a senior backend engineer with deep Java expertise and experience designing distributed systems.'),
(102, 'ML Engineer', 'Seeking a data scientist or ML engineer familiar with NLP and large language models.');
可以通過 AI_FILTER 把職業要求和候選人簡介做語義匹配,篩選出合適的候選人:
SELECT
c.candidate_id, c.name,
j.job_id, j.title
FROM candidate_profiles AS c
JOIN job_requirements AS j
WHERE AI_FILTER(CONCAT('Does the following candidate self-introduction match the job description?',
'Job: ', j.jd_text, ' Candidate: ', c.self_intro));
得到結果:
+--------------+-------+--------+------------------+
| candidate_id | name | job_id | title |
+--------------+-------+--------+------------------+
| 3 | Cathy | 102 | ML Engineer |
| 1 | Alice | 101 | Backend Engineer |
+--------------+-------+--------+------------------+
二、搜索功能全面升級,賦能全文檢索
針對企業級搜索場景的多樣化需求,本次版本完善搜索能力矩陣,提供更精準、更靈活的文本檢索體驗:
01 新增 Search 函數:統一入口的輕量 DSL 全文檢索
核心亮點
- 一個函數搞定全文檢索:將複雜文本檢索算子收攏到
SEARCH()統一入口,語法貼近 Elasticsearch Query String,極大降低 SQL 拼接複雜度與遷移成本。 - 多條件索引下推:複雜檢索條件直接下推至倒排索引執行,避免“解析一次、拼接一次”的重複開銷,顯著提升性能。
DSL 語法支持簡介
-
當前版本支持的語法功能:
- 詞項查詢(Term):
field:value - ANY / ALL 多值匹配:
field:ANY(v1 v2 ...)/field:ALL(v1 v2 ...) - 布爾組合:
AND / OR / NOT與括號分組 - 多字段搜索:在一個
search()中對多個字段做布爾組合
- 詞項查詢(Term):
-
後續版本會持續迭代以支持以下語法功能:
- 短語
- 前綴
- 通配符
- 正則
- 範圍
- 列表
使用方式舉例
-- 詞項查詢
SELECT * FROM docs WHERE search('title:apache');
-- ANY:匹配任意一個值
SELECT * FROM docs WHERE search('tags:ANY(java python golang)');
-- ALL:同時包含多個值
SELECT * FROM docs WHERE search('tags:ALL(machine learning)');
-- 布爾 + 多字段
SELECT * FROM docs
WHERE search('(title:Doris OR content:database) AND NOT category:archived');
-- 結合結構化過濾(結構化條件不參與打分)
SELECT * FROM docs
WHERE search('title:apache') AND publish_date >= '2025-01-01';
02 文本檢索打分
為了更好的支持混合檢索場景,Doris4.0 版本引入業界主流的 BM25 相關性評分算法,替代傳統的 TF-IDF 算法。BM25 可根據文檔長度動態調整詞頻權重,在長文本、多字段檢索場景下(如日誌分析、文檔檢索),顯著提升結果相關性與檢索準確性。
使用方式舉例
SELECT *, score() as score
FROM search_demo
WHERE content MATCH_ANY 'search query'
ORDER BY score DESC
LIMIT 10;
功能特性和限制
支持的索引類型
- Tokenized 索引:預定義分詞器和自定義分詞器
- 非 Tokenized 索引:不分詞索引
支持的文本檢索算子
- MATCH_ANY
- MATCH_ALL
- MATCH_PHRASE
- MATCH_PHRASE_PREFIX
- SEARCH
注意事項
- 分數範圍:BM25 分數沒有固定的上下界,分數的相對大小比絕對值更有意義
- 空查詢:如果查詢詞項在集合中不存在,將返回 0 分
- 文檔長度影響:較短的文檔在包含查詢詞項時通常獲得更高分數
- 查詢詞項數量:多詞項查詢的分數是各詞項分數的組合(相加)
03 倒排索引分詞能力增強
Doris 在 3.1 版本初步提供了分詞能力,在 4.0 版本中,我們對分詞能力進一步增強,能夠滿足用户在不同場景下的分詞和文本檢索需求。
增加三種內置分詞器
ICU(International Components for Unicode)分詞器
- 適用場景:包含複雜文字系統的國際化文本,特別適合多語言混合文檔
- 分詞能力舉例
SELECT TOKENIZE('مرحبا بالعالم Hello 世界', '"parser"="icu"');
-- 結果: ["مرحبا", "بالعالم", "Hello", "世界"]
SELECT TOKENIZE('มนไมเปนไปตามความตองการ', '"parser"="icu"');
-- 結果: ["มน", "ไมเปน", "ไป", "ตาม", "ความ", "ตองการ"]
IK 分詞器
- 適用場景:對分詞質量要求較高的中文文本處理
- ik_smart:智能模式,詞少且更長,語義集中,適合精確搜索
- ik_max_word:最細粒度模式,更多短詞,覆蓋更全面,適合召回搜索
- 分詞能力舉例
SELECT TOKENIZE('中華人民共和國國歌', '"parser"="ik","parser_mode"="ik_smart"');
-- 結果: ["中華人民共和國", "國歌"]
SELECT TOKENIZE('中華人民共和國國歌', '"parser"="ik","parser_mode"="ik_max_word"');
-- 結果: ["中華人民共和國", "中華人民", "中華", "華人", "人民共和國", "人民", "共和國", "共和", "國歌"]
Basic 分詞器
- 適用場景:簡單場景、對性能要求極高的場景,可以作為日誌場景中 unicode 分詞器的平替
- 分詞能力舉例
-- 英文文本分詞
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"]
新增自定義分詞能力
- 管道化組合:通過 char filter、tokenizer 與多個 token filter 的鏈式配置,構建自定義文本處理流程。
- 組件複用:常用的 tokenizer 和 filter 可在多個 analyzer 中共享,減少重複定義,降低維護成本。
- 用户可以通過 Doris 提供的自定義分詞機制,支持靈活組合 char filter、tokenizer 和 token filter,從而為不同字段定製合適的分詞流程,滿足複雜場景下的個性化文本檢索需求。
使用方式舉例 1
- 創建類型為 word_delimiter 的 token filter,通過配置 Word Delimiter Filter,將點號(.)和下劃線(_)設置為分隔符。
- 創建自定義分詞器 complex_identifier_analyzer,引用 token filter complex_word_splitter。
-- 1. 創建自定義 token filter
CREATE INVERTED INDEX TOKEN_FILTER IF NOT EXISTS complex_word_splitter
PROPERTIES
(
"type" = "word_delimiter",
"type_table" = "[. => SUBWORD_DELIM], [_ => SUBWORD_DELIM]");
-- 2. 創建自定義分詞器
CREATE INVERTED INDEX ANALYZER IF NOT EXISTS complex_identifier_analyzer
PROPERTIES
(
"tokenizer" = "standard",
"token_filter" = "complex_word_splitter, lowercase"
);
SELECT TOKENIZE(‘apy217.39_202501260000026_526’, ‘”analyzer“=” complex_identifier_analyzer“‘);
-- 結果為[apy]、[217]、[39]、[202501260000026]、[526]
-- MATCH(‘apy217’)或者MATCH(‘202501260000026’)都可以命中
使用方式舉例 2
- 創建類型為 char_group 的 tokenizer multi_value_tokenizer,只將符號 | 設置為分隔符。
- 創建自定義分詞器 multi_value_analyzer,引用 tokenizer multi_value_tokenizer 。
-- 創建用於多值列分割的 char group tokenizer
CREATE INVERTED INDEX TOKENIZER IF NOT EXISTS multi_value_tokenizer
PROPERTIES
(
"type" = "char_group",
"tokenize_on_chars" = "[|]",
"max_token_length" = "255"
);
-- 創建多值列分詞器
CREATE INVERTED INDEX ANALYZER IF NOT EXISTS multi_value_analyzer
PROPERTIES
(
"tokenizer" = "multi_value_tokenizer",
"token_filter" = "lowercase, asciifolding"
);
SELECT tokenize('alice|123456|company', '"analyzer"="multi_value_analyzer"');
-- 結果為[alice]、[123456]、[company]
-- MATCH_ANY(‘alice’)或者MATCH_ANY(‘123456’)都可以命中
三、離線計算能力強化,保障大規模任務穩定運行
當前越來越多的用户將 ETL 數據加工,多表物化視圖處理等離線計算任務遷移到 Doris 上運行,針對離線批處理場景的資源消耗大、任務易溢出等痛點,4.0 新增 Spill Disk 功能,當離線計算任務的內存佔用超出閾值時,自動將部分中間數據寫入磁盤,避免因內存不足導致任務失敗,大幅提升大規模離線任務的穩定性與容錯能力。目前支持落盤的算子有:
- Hash Join 算子
- 聚合算子
- 排序算子
- CTE 算子
BE 配置項
spill_storage_root_path=/mnt/disk1/spilltest/doris/be/storage;/mnt/disk2/doris-spill;/mnt/disk3/doris-spill
spill_storage_limit=100%
- spill_storage_root_path:查詢中間結果落盤文件存儲路徑,默認和 storage_root_path 一樣。
- spill_storage_limit: 落盤文件佔用磁盤空間限制。可以配置具體的空間大小(比如 100G, 1T)或者百分比,默認 20%。如果 spill_storage_root_path 配置單獨的磁盤,可以設置為 100%。這個參數主要是防止落盤佔用太多的磁盤空間,導致無法進行正常的數據存儲。
FE Session Variable
set enable_spill=true;
set exec_mem_limit = 10g;
set query_timeout = 3600;
- enable_spill 表示一個 query 是否開啓落盤,默認關閉;如果開啓,在內存緊張的情況下,會觸發查詢落盤;
- exec_mem_limit 表示一個 query 使用的最大的內存大小;
- query_timeout 開啓落盤,查詢時間可能會顯著增加,query_timeout 需要進行調整。
一旦落盤發生,用户可以通過多種方式監測落盤的執行狀況。
審計日誌
FE audit log 中增加了SpillWriteBytesToLocalStorage和SpillReadBytesFromLocalStorage字段,分別表示落盤時寫盤和讀盤數據總量。
SpillWriteBytesToLocalStorage=503412182|SpillReadBytesFromLocalStorage=503412182
Profile
如果查詢過程中觸發了落盤,在 Query Profile 中增加了Spill 前綴的一些 Counter 進行標記和落盤相關 counter。以 HashJoin 時 Build HashTable 為例,可以看到下面的 Counter:
PARTITIONED_HASH_JOIN_SINK_OPERATOR (id=4 , nereids_id=179):(ExecTime: 6sec351ms)
- Spilled: true
- CloseTime: 528ns
- ExecTime: 6sec351ms
- InitTime: 5.751us
- InputRows: 6.001215M (6001215)
- MemoryUsage: 0.00
- MemoryUsagePeak: 554.42 MB
- MemoryUsageReserved: 1024.00 KB
- OpenTime: 2.267ms
- PendingFinishDependency: 0ns
- SpillBuildTime: 2sec437ms
- SpillInMemRow: 0
- SpillMaxRowsOfPartition: 68.569K (68569)
- SpillMinRowsOfPartition: 67.455K (67455)
- SpillPartitionShuffleTime: 836.302ms
- SpillPartitionTime: 131.839ms
- SpillTotalTime: 5sec563ms
- SpillWriteBlockBytes: 714.13 MB
- SpillWriteBlockCount: 1.344K (1344)
- SpillWriteFileBytes: 244.40 MB
- SpillWriteFileTime: 350.754ms
- SpillWriteFileTotalCount: 32
- SpillWriteRows: 6.001215M (6001215)
- SpillWriteSerializeBlockTime: 4sec378ms
- SpillWriteTaskCount: 417
- SpillWriteTaskWaitInQueueCount: 0
- SpillWriteTaskWaitInQueueTime: 8.731ms
- SpillWriteTime: 5sec549ms
系統表 backend_active_tasks
增加了SPILL_WRITE_BYTES_TO_LOCAL_STORAGE和SPILL_READ_BYTES_FROM_LOCAL_STORAGE字段,分別表示一個查詢目前落盤中間結果寫盤數據和讀盤數據總量。
mysql [information_schema]>select * from backend_active_tasks;
+-------+------------+-------------------+-----------------------------------+--------------+------------------+-----------+------------+----------------------+---------------------------+--------------------+-------------------+------------+------------------------------------+-------------------------------------+
| BE_ID | FE_HOST | WORKLOAD_GROUP_ID | QUERY_ID | TASK_TIME_MS | TASK_CPU_TIME_MS | SCAN_ROWS | SCAN_BYTES | BE_PEAK_MEMORY_BYTES | CURRENT_USED_MEMORY_BYTES | SHUFFLE_SEND_BYTES | SHUFFLE_SEND_ROWS | QUERY_TYPE | SPILL_WRITE_BYTES_TO_LOCAL_STORAGE | SPILL_READ_BYTES_FROM_LOCAL_STORAGE |
+-------+------------+-------------------+-----------------------------------+--------------+------------------+-----------+------------+----------------------+---------------------------+--------------------+-------------------+------------+------------------------------------+-------------------------------------+
| 10009 | 10.16.10.8 | 1 | 6f08c74afbd44fff-9af951270933842d | 13612 | 11025 | 12002430 | 1960955904 | 733243057 | 70113260 | 0 | 0 | SELECT | 508110119 | 26383070 |
| 10009 | 10.16.10.8 | 1 | 871d643b87bf447b-865eb799403bec96 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | SELECT | 0 | 0 |
+-------+------------+-------------------+-----------------------------------+--------------+------------------+-----------+------------+----------------------+---------------------------+--------------------+-------------------+------------+------------------------------------+-------------------------------------+
2 rows in set (0.00 sec)
測試
為驗證落盤功能的穩定性,我們採用 TPC-DS 10TB 標準數據集 開展測試,測試環境配置為 3 台 BE 服務器(每台 16 核 CPU、64GB 內存)。BE 的內存與數據規模的比例為 1:52。測試結果顯示,整體運行時長為 28102.386 秒,且成功跑完 TPC-DS 基準測試中的全部 99 條查詢,驗證了落盤功能的基礎穩定性。
具體數據請參考:https://doris.apache.org/docs/dev/admin-manual/workload-management/spill-disk。
四、數據質量全鏈路保障,築牢分析結果可信基石
數據正確性是企業制定決策的核心前提與關鍵基石。為進一步夯實這一基礎,4.0 版本對大量函數的運行行為進行了系統性梳理與規範,從數據導入環節到計算分析環節構建全鏈路校驗機制,全面保障數據處理結果的準確性與可靠性,為企業決策提供堅實的數據支撐。
注:數據質量問題的梳理會導致一些行為跟過去產生差異,升級之前請務必仔細閲讀文檔並提前做好環境測試。
01 Cast
CAST 是 SQL 中邏輯最複雜的函數之一,其核心作用是實現不同數據類型間的轉換 —— 這一過程不僅需處理大量細碎的格式規則與邊界場景,更因涉及類型語義的精準映射,成為實際使用中極易出錯的環節。尤其在數據導入場景中,本質是將外部字符串轉換為數據庫內部類型的 CAST 操作,因此 CAST 的行為直接決定了導入邏輯的準確性與穩定性。同時,我們可以預見未來的數據庫將大量的被 AI 來操作,而 AI 需要對數據庫的行為有明確的定義,為此,我們引入了 BNF 範式,希望通過範式定義的方式,為開發者和 AI Agent 提供清晰的操作依據。例如僅 DATE 類型的 CAST 就已通過 BNF 覆蓋數十種格式組合場景(https://doris.apache.org/zh-CN/docs/dev/sql-manual/basic-elem...),同時在測試階段我們通過這些規則,派生出百萬級的測試 case,保障結果的正確性。
<datetime> ::= <date> (("T" | " ") <time> <whitespace>* <offset>?)?
| <digit>{14} <fraction>? <whitespace>* <offset>?
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
<date> ::= <year> ("-" | "/") <month1> ("-" | "/") <day1>
| <year> <month2> <day2>
<year> ::= <digit>{2} | <digit>{4} ; 1970 為界
<month1> ::= <digit>{1,2} ; 01–12
<day1> ::= <digit>{1,2} ; 01–28/29/30/31 視月份而定
<month2> ::= <digit>{2} ; 01–12
<day2> ::= <digit>{2} ; 01–28/29/30/31 視月份而定
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
<time> ::= <hour1> (":" <minute1> (":" <second1> <fraction>?)?)?
| <hour2> (<minute2> (<second2> <fraction>?)?)?
<hour1> ::= <digit>{1,2} ; 00–23
<minute1> ::= <digit>{1,2} ; 00–59
<second1> ::= <digit>{1,2} ; 00–59
<hour2> ::= <digit>{2} ; 00–23
<minute2> ::= <digit>{2} ; 00–59
<second2> ::= <digit>{2} ; 00–59
<fraction> ::= "." <digit>*
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
<offset> ::= ( "+" | "-" ) <hour-offset> [ ":"? <minute-offset> ]
| <special-tz>
| <long-tz>
<hour-offset> ::= <digit>{1,2} ; 0–14
<minute-offset> ::= <digit>{2} ; 00/30/45
<special-tz> ::= "CST" | "UTC" | "GMT" | "ZULU" | "Z" ; 忽略大小寫
<long-tz> ::= ( ^<whitespace> )+ ; e.g. America/New_York
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
<digit> ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
<area> ::= <alpha>+
<location> ::= (<alpha> | "_")+
<alpha> ::= "A" | … | "Z" | "a" | … | "z"
<whitespace> ::= " " | "\t" | "\n" | "\r" | "\v" | "\f"
02 嚴格模式、非嚴格模式、TRY_CAST
在 Doris 4.0 中,對CAST操作增加了嚴格模式、非嚴格模式(通過 enable_strict_cast 來控制)以及TRY_CAST函數,以更好地處理數據類型轉換時的各種情況。具體如下:
- 嚴格模式:系統會依據預定義的 BNF(語法規則,對輸入數據的格式、類型、取值範圍進行嚴格校驗:若數據不符合規則(如字段類型應為 “數值型” 卻傳入字符串、日期格式不符合 “YYYY-MM-DD” 規範),系統會直接終止數據處理流程並拋出明確報錯(含具體不符合規則的字段與原因),杜絕不合法數據進入存儲或計算環節。這種 “零容忍” 的校驗邏輯,與 PostgreSQL 數據庫的嚴格數據校驗行為高度一致,能從源頭保障數據質量的準確性與一致性,因此在對數據可靠性要求極高的場景中不可或缺 —— 例如金融行業的交易對賬、財務領域的賬單核算、政務系統的信息登記等場景,一旦出現不合法數據(如交易金額為負數、賬單日期格式錯誤),可能引發資金損失、合規風險或業務流程混亂。
- 非嚴格模式:系統同樣會依據 BNF 規則校驗數據,但採用 “容錯式” 處理邏輯:若數據不符合規則,不會終止流程或報錯,而是自動將不合法數據轉換為 NULL 值後繼續執行 SQL(例如將字符串 “xyz” 轉換為數值型 NULL),確保 SQL 任務能正常完成,優先保障業務流程的連續性與執行效率。這種模式更適用於對 “數據完整性要求較低、但對 SQL 執行成功率要求高” 的場景 —— 例如日誌數據處理、用户行為數據清洗、臨時數據分析等場景,此類場景中數據量龐大且來源複雜(如 APP 日誌可能因設備異常產生格式錯亂字段),若因少量不合法數據中斷整個 SQL 任務,會大幅降低處理效率,且少量 NULL 值對整體分析結果(如統計活躍用户數、點擊量)影響極小。
enable_strict_cast 是在一個語句級別控制 cast 的行為的方式,但是可能會出現,在一個 SQL 中有多個 cast 函數,有一部分函數用户希望用嚴格模式,另外一部分函數使用非嚴格模式,所以我們引入了TRY_CAST 函數。
TRY_CAST函數的作用是將一個表達式轉換為指定的數據類型,如果轉換成功則返回轉換後的值,如果轉換失敗則返回 NULL。其語法為TRY_CAST(source_expr AS target_type),其中source_expr是要轉換的表達式,target_type是目標數據類型。例如,TRY_CAST('123' AS INT)會返回 123,而TRY_CAST('abc' AS INT)會返回 NULL。TRY_CAST函數提供了一種更靈活的類型轉換方式,在不需要嚴格保證轉換成功的場景下,可以使用該函數來避免因轉換失敗而導致的錯誤。
03 浮點類型計算
Doris 提供了兩種浮點數據類型:FLOAT 和 DOUBLE,但是在有 INF 或者 NaN 的時候由於行為不確定,導致 Order BY 或者 Group BY 時結果可能錯誤,在這個版本中我們規範並且明確了這個行為。
算術運算
Doris 的浮點數支持常見的加減乘除等算術運算。需要特別注意的是,Doris 在處理浮點數除以 0 的情況時,並不完全遵循 IEEE 754 標準。
Doris 在這方面參考了 PostgreSQL 的實現,當除以 0 時不會生成特殊值,而是返回 SQL NULL:
比較運算
IEEE 標準定義的浮點數比較與通常的整數比較有一些重要區別。例如,負零和正零被視為相等,而任何 NaN 值與任何其他值(包括它自身)比較時都不相等。所有有限浮點數都嚴格小於 +∞,嚴格大於 -∞。
為了確保結果的一致性和可預測性,Doris 對 NaN 的處理與 IEEE 標準有所不同。 在 Doris 中,NaN 被視為大於所有其他值(包括 Infinity),NaN 等於 NaN。
mysql> select * from sort_float order by d;
+------+-----------+
| id | d |
+------+-----------+
| 5 | -Infinity |
| 2 | -123 |
| 1 | 123 |
| 4 | Infinity |
| 8 | NaN |
| 9 | NaN |
+------+-----------+
mysql> select
cast('Nan' as double) = cast('Nan' as double) ,
cast('Nan' as double) > cast('Inf' as double) ,
cast('Nan' as double) > cast('123456.789' as double);
+-----------------------------------------------+-----------------------------------------------+------------------------------------------------------+
| cast('Nan' as double) = cast('Nan' as double) | cast('Nan' as double) > cast('Inf' as double) | cast('Nan' as double) > cast('123456.789' as double) |
+-----------------------------------------------+-----------------------------------------------+------------------------------------------------------+
| 1 | 1 | 1 |
+-----------------------------------------------+-----------------------------------------------+------------------------------------------------------+
04 日期函數
本次優化圍繞日期函數與時區支持兩大維度展開,進一步提升了數據處理的準確性與適用性:
統一日期溢出行為:針對眾多日期函數在日期溢出場景(如日期小於 0000-01-01 或大於 9999-12-31)下的行為進行標準化修正,此前不同函數處理溢出時結果不一致的問題被解決,當前所有相關函數在觸發日期溢出時均統一返回報錯,避免因異常結果導致的數據計算偏差。
擴展日期函數支持範圍:將部分日期類型函數的參數簽名從 int32 升級為 int64。這一調整突破了原 int32 類型對日期範圍的限制,使相關函數能夠支持更大跨度的日期計算。
優化時區支持描述:結合 Doris 時區管理的實際邏輯,對時區支持內容進行了更精準的補充與説明,明確了 system_time_zone 與 time_zone 兩大核心參數的作用、修改方式,以及時區對日期函數(如 FROM_UNIXTIME、UNIX_TIMESTAMP)、數據導入轉換的具體影響,為用户配置與使用時區功能提供更清晰的指引。
為構建真正 Agent-Friendly 的數據庫生態,並幫助大模型更精準、深度地理解 Doris,我們對 Doris 的 SQL Reference 進行了系統性完善,具體涵蓋數據類型定義、函數定義、數據變換規則等核心內容,為 AI 與數據庫的協同交互奠定清晰、可靠的技術基礎。 這項工作得到了很多社區小夥伴的支持,他們的智慧與力量為項目注入了關鍵活力。我們也熱切期待更多社區同仁加入進來,與我們攜手共建,在技術探索與生態完善的道路上凝聚更多力量,共創更大價值。
五、性能優化
01 TopN 延遲物化
SELECT * FROM tableX ORDER BY columnA ASC/DESC LIMIT N 作為典型的 TopN 查詢模式,廣泛應用於日誌分析、向量檢索、數據探查等高頻場景。由於此類查詢未攜帶過濾條件,當數據規模龐大時,傳統執行方式需對全表數據進行掃描並排序,這會導致大量不必要的數據讀取,引發嚴重的讀放大問題。尤其在高併發請求或大數據量存儲場景中,該類查詢的性能瓶頸更為顯著,用户對其優化需求極為迫切。
為攻克這一痛點,我們引入了「延遲物化」優化機制,將 TopN 查詢拆解為兩階段高效執行:第一階段僅讀取排序字段(columnA)與用於定位數據的主鍵 / 行標識,通過排序快速篩選出符合 LIMIT N 條件的目標行;第二階段再基於行標識精準讀取目標行的所有列數據。
在 4.0 上,我們對這個能力做出了更進一步的擴展:
- 支持在多表關聯的時候也進行 TopN 的延遲物化
- 支持在外表查詢時進行 TopN 的延遲物化
在這兩個新的場景之中,這個方案能大幅削減非必要列的讀取量,從根源上降低讀放大效應,在寬表小 LIMIT 場景下 TopN 查詢的執行效率有幾十倍的提升。
02 SQL Cache 緩存
SQL Cache 是 Doris 在早期版本中提供的功能,受限於很多條件,默認處於關閉狀態,在這個版本中,我們系統的梳理了可能影響 SQL Cache 結果的問題,例如 Catalog、DB、Table、Column、Row 查詢權限變更,Session variables 發生變更,出現常量摺疊規則不能化簡的非確定函數等,為了確保 SQL Cache 結果的正確性,該功能現已默認開啓。
同時我們對優化器解析 SQL 的性能做了巨大的改進提升,具體而言,SQL 解析性能提升了 100 倍。例如以下 SQL,其中 big_view 是一個包含嵌套視圖的大型視圖,裏面有嵌套的 view,共計 163 個 join 和 17 個 union,我們將 SQL 解析的性能從 400ms 提升到了 2ms。這個優化不僅對 SQL Cache 幫助很大,在 Doris 的高併發查詢場景中也有明顯提升。
SELECT *,now() as etl_time from big_view;
03 JSON 性能優化
JSON 是半結構化數據常見的一種存儲方式,在 4.0 版本我們對 JSONB 也進行了升級。一方面,新增對 Decimal 類型的支持,完善了 JSON 中 Number 類型與 Doris 內部類型的映射體系(此前已覆蓋 Int8/Int16/Int32/Int64/Int128/Float/Double 等),進一步滿足高精度數值場景的存儲與處理需求,避免大數值或高精度數據在 JSON 轉換中因類型適配問題導致的精度損失,這有助於 Variant 類型的推導;另一方面,對 JSONB 相關的全量函數(如 json_extract 系列、json_exists_path、json_type 等)進行系統性性能優化,優化後函數執行效率普遍提升 30% 以上,顯著加快了 JSON 字段提取、類型判斷、路徑校驗等高頻操作的處理速度,為半結構化數據的高效分析提供更強支撐。
相關功能細節可參考 Doris 官方文檔:https://doris.apache.org/zh-CN/docs/dev/sql-manual/basic-element/sql-data-types/semi-structured/JSON
六、更易用的資源管控
4.0 版本對 Workload Group 的使用機制進行了優化:統一了 CPU 與內存的軟限、硬限定義方式,無需再通過各類配置項單獨開啓軟限或硬限功能,並且同時支持在同一 Workload Group 中並存使用軟限與硬限。優化後不僅簡化了參數配置流程,還增強了 Workload Group 的使用靈活性,能更精準地滿足多樣化的資源管控需求。
MIN_CPU_PERCENT 和 MAX_CPU_PERCENT 定義了在出現 CPU 爭用時,Workload Group 中所有請求的最低和最高保證 CPU 資源。
- MAX_CPU_PERCENT(最大 CPU 百分比)是該池中 CPU 帶寬的最大限制,不論當前 CPU 使用率是多少, 當前 Workload Group 的 CPU 使用率超過都不會超過 MAX_CPU_PERCENT。
- MIN_CPU_PERCENT(最小 CPU 百分比)是為該 Workload 預留的 CPU 帶寬,在存在爭用時,其他池無法使用這部分帶寬, 但是當資源空閒時可以使用超過 MIN_CPU_PERCENT 的帶寬。
例如,假設某公司的銷售部門和市場部門共享同一個 Doris 實例。銷售部門的工作負載是 CPU 密集型的,且包含高優先級查詢;市場部門的工作負載同樣是 CPU 密集型,但查詢優先級較低。通過為每個部門創建單獨的 Workload Group,可以為銷售 Workload Group 分配 40% 的最小 CPU 百分比,為市場 Workload Group 分配 30% 的最大 CPU 百分比。這種配置能確保銷售工作負載獲得所需的 CPU 資源,同時市場工作負載不會影響銷售工作負載對 CPU 的需求。
MIN_MEMORY_PERCENT 和 MAX_MEMORY_PERCENT 是 Workload Group 可以使用的最小和最大內存量。
- MAX_MEMORY_PERCENT,意味着當請求在該池中運行時,它們佔用的內存絕不會超過總內存的這一百分比,一旦超過那麼 Query 將會觸發落盤或者被 Kill。
- MIN_MEMORY_PERCENT,為某個池設置最小內存值,當資源空閒時,可以使用超過 MIN_MEMORY_PERCENT 的內存,但是當內存不足時,系統將按照 MIN_MEMORY_PERCENT(最小內存百分比)分配內存,可能會選取一些 Query Kill,將 Workload Group 的內存使用量降低到 MIN_MEMORY_PERCENT,以確保其他 Workload Group 有足夠的內存可用。
與落盤相結合
在這個版本中,我們將 Workload Group 的內存管理能力與落盤功能進行融合,用户不僅可以通過為每一個 query 設置內存大小來控制落盤,還可以通過 Workload Group 的 Slot 機制來實現動態落盤,在 Workload Group 之上實現了以下策略:
- none,默認值,表示不啓用;在這種方式下,query 就儘量的使用內存,但是一旦達到 Workload Group 的上限,就會觸發落盤;此時不會根據查詢的大小選擇。
- fixed,每個 query 可以使用的的內存 =
workload group的mem_limit * query_slot_count/ max_concurrency;這種內存分配策略實際是按照併發,給每個 query 分配固定的內存。 - dynamic,每個 query 可以使用的的內存 =
workload group的mem_limit * query_slot_count/ sum(running query slots),該參數克服了 fixed 模式下存在的 Slot 未使用的情況;實際是把大的查詢先落盤。
fixed 或者 dynamic 設置的都是 query 的硬限,一旦超過,就會落盤或者 kill,並且覆蓋用户設置的靜態內存分配的參數。因此設置 slot_memory_policy 時,一定要注意 Workload Group 的 max_concurrency,否則會出現內存不足的問題。
總結
本次 Apache Doris 新版本通過 AI 與搜索能力的深度融合、離線計算的穩定性提升、性能與易用性的雙重優化,進一步拓寬了數據庫的應用邊界,可更好地支撐企業從傳統 BI 分析到 AI 智能檢索、從實時查詢到大規模離線批處理的全場景數據分析需求。無論是互聯網、金融、零售等行業的實時報表、用户行為分析,還是政務、醫療領域的文檔檢索、大規模數據批處理,新版本 Doris 都將為用户提供更高效、更可靠的數據分析體驗。
目前,Apache Doris 新版本已開放下載,詳細特性文檔與升級指南可訪問官方網站(https://doris.apache.org)查看,歡迎社區用户體驗與反饋!
致謝
在此,再次向所有參與版本研發、測試和需求反饋的貢獻者們表示最衷心的感謝:
Pxl,walter,Gabriel,Mingyu Chen(Rayner),Mryange,morrySnow,zhangdong,lihangyu,zhangstar333,hui lai,Calvin Kirs,deardeng,Dongyang Li,Kaijie Chen,Xinyi Zou,minghong,meiyi,James/Jibing-Li,seawinde,abmdocrt,Yongqiang YANG,Sun Chenyang,wangbo,starocean999,Socrates/蘇小剛,Gavin Chou,924060929,HappenLee,yiguolei,daidai,Lei Zhang,zhengyu,zy-kkk,zclllyybb/zclllhhjj,bobhan1,amory,zhiqiang,Jerry Hu,Xin Liao,Siyang Tang,LiBinfeng,Tiewei Fang,Luwei,huanghaibin,Qi Chen,TengJianPing,謝健,Lightman,zhannngchen,koarz,xy720,kkop,HHoflittlefish777,xzj7019,Ashin Gau,lw112,plat1ko,shuke,yagagagaga,shee,zgxme,qiye,zfr95,slothever,Xujian Duan,Yulei-Yang,Jack,Kang,Lijia Liu,linrrarity,Petrichor,Thearas,Uniqueyou,dwdwqfwe,Refrain,catpineapple,smiletan,wudi,caiconghui,camby,zhangyuan,jakevin,Chester,Mingxi,Rijesh Kunhi Parambattu,admiring_xm,zxealous,XLPE,chunping,sparrow,xueweizhang,Adonis Ling,Jiwen liu,KassieZ,Liu Zhenlong,MoanasDaddyXu,Peyz,神技圈子,133tosakarin,FreeOnePlus,Ryan19929,Yixuan Wang,htyoung,smallx,Butao Zhang,Ceng,GentleCold,GoGoWen,HonestManXin,Liqf,Luzhijing,Shuo Wang,Wen Zhenghu,Xr Ling,Zhiguo Wu,Zijie Lu,feifeifeimoon,heguanhui,toms,wudongliang,yangshijie,yongjinhou,yulihua,zhangm365,Amos Bird,AndersZ,Ganlin Zhao,Jeffrey,John Zhang,M1saka,SWEI,XueYuhai,Yao-MR,York Cao,caoliang-web,echo-dundun,huanghg1994,lide,lzy,nivane,nsivarajan,py023,vlt,wlong,zhaorongsheng,AlexYue,Arjun Anandkumar,Arnout Engelen,Benjaminwei,DayuanX,DogDu,DuRipeng,Emmanuel Ferdman,Fangyuan Deng,Guangdong Liu,HB,He xueyu,Hongkun Xu,Hu Yanjun,JinYang,KeeProMise,Muhammet Sakarya,Nya~,On-Work-Song,Shane,Stalary,StarryVerse,TsukiokaKogane,Udit Chaudhary,Xin Li,XnY-wei,Xu Chen,XuJianxu,XuPengfei,Yijia Su,ZhenchaoXu,cat-with-cat,elon-X,gnehil,hongyu guo,ivin,jw-sun,koi,liuzhenwei,msridhar78,noixcn,nsn_huang,peterylh,shouchengShen,spaces-x,wangchuang,wangjing,wangqt,wubiao,xuchenhao,xyf,yanmingfu,yi wang,z404289981,zjj,zzwwhh,İsmail Tosun,趙碩