一、安裝部署
安裝教程:GitHub地址
Doc文檔:Apache Doris 簡介 - Apache Doris
二、功能及作用
- Apache Doris 是一款基于MPP 架構的高性能、實時分析型數據庫。它以高效、簡單和統一的特性著稱,能夠在亞秒級的時間內返回海量數據的查詢結果。Doris 既能支持高并發的點查詢場景,也能支持高吞吐的復雜分析場景。
- 基于這些優勢,Apache Doris 非常適合用于報表分析、即席查詢、統一數倉構建、數據湖聯邦查詢加速等場景。用戶可以基于 Doris 構建大屏看板、用戶行為分析、AB 實驗平臺、日志檢索分析、用戶畫像分析、訂單分析等應用,適合處理結構化數據
三、整體架構
Apache Doris 使用 MySQL 協議,與 MySQL 語法高度兼容,并支持標準 SQL。用戶可以通過各種客戶端工具訪問 Apache Doris,它與BI工具無縫集成 - Frontend(FE):主要負責用戶請求的接入、查詢解析規劃、元數據的管理、節點管理相關工作
- Master節點:負責元數據的讀寫。當 Master 節點的元數據發生變更后,會通過 BDB JE 協議同步給 Follower 或 Observer 節點
- Follower節點:負責讀取元數據。當 Master 節點發生故障時,可以選取一個 Follower 節點作為新的 Master 節點
- Observer節點:負責讀取元數據,主要目的是增加集群的查詢并發能力。Observer 節點不參與集群的選主過程
- Backend(BE):主要負責數據存儲、查詢計劃的執行
四、數據表設計
1. 數據模型
Doris 中建表時需要指定表模型,以定義數據存儲與管理方式。在 Doris 中提供了明細模型、聚合模型以及主鍵模型三種表模型,可以應對不同的應用場景需求。
- 明細模型(Duplicate Key Model)(默認):允許指定的 Key 列重復,Doirs 存儲層保留所有寫入的數據,適用于必須保留所有原始數據記錄的情況;
- 主鍵模型(Unique Key Model):每一行的 Key 值唯一,可確保給定的 Key 列不會存在重復行,Doris 存儲層對每個 key 只保留最新寫入的數據,適用于數據更新的情況;
- 聚合模型(Aggregate Key Model):可根據 Key 列聚合數據,Doris 存儲層保留聚合后的數據,從而可以減少存儲空間和提升查詢性能;通常用于需要匯總或聚合信息(如總數或平均值)的情況。
1.1 明細模型(Duplicate Key Model)
一般明細模型中的數據只進行追加,舊數據不會更新。明細模型適用于需要存儲全量原始數據的場景:如日志存儲、用戶行為數據、交易數據。
1.1.1 建表
在建表時,可以通過 DUPLICATE KEY 關鍵字指定明細模型。明細表必須指定數據的 Key 列,用于在存儲時對數據進行排序。下例的明細表中存儲了日志信息,并針對于 log_time、log_type 及 error_code 三列進行了排序:
CREATE TABLE IF NOT EXISTS example_tbl_duplicate
(log_time DATETIME NOT NULL,log_type INT NOT NULL,error_code INT,error_msg VARCHAR(1024),op_id BIGINT,op_time DATETIME
)
ENGINE = OLAP --指定使用 Doris 的 OLAP 引擎,支持高效數據分析
==DUPLICATE KEY(log_time, log_type, error_code) --log_time, log_type, error_code作為排序鍵,優化按時間和類型的查詢
DISTRIBUTED BY HASH(log_type) BUCKETS 10 --按log_type字段進行哈希分桶、創建 10 個數據桶
PROPERTIES ("replication_num" = "1" -- 將副本數設置為1,與可用后端節點數匹配
);
1.1.2 數據插入與存儲
-- 4 rows raw data
INSERT INTO example_tbl_duplicate VALUES
('2024-11-01 00:00:00', 2, 2, 'timeout', 12, '2024-11-01 01:00:00'),
('2024-11-02 00:00:00', 1, 2, 'success', 13, '2024-11-02 01:00:00'),
('2024-11-03 00:00:00', 2, 2, 'unknown', 13, '2024-11-03 01:00:00'),
('2024-11-04 00:00:00', 2, 2, 'unknown', 12, '2024-11-04 01:00:00');-- insert into 2 rows
INSERT INTO example_tbl_duplicate VALUES
('2024-11-01 00:00:00', 2, 2, 'timeout', 12, '2024-11-01 01:00:00'),
('2024-11-01 00:00:00', 2, 2, 'unknown', 13, '2024-11-01 01:00:00');-- check the rows of table
SELECT * FROM example_tbl_duplicate;
- 結果如下:
明細模型默認存儲排序
ORDER BY 顯式排序
- 不同于直接
SELECT * FROM example_tbl_duplicate ORDER BY log_time, log_type, error_code;
默認查詢是 “底層存儲順序的直接呈現”(受分桶、寫入等影響),ORDER BY 是 “結果集的強制重排” 。
1.2 主鍵模型(Unique Key Model)
需要更新數據時,可以選擇主鍵模型(Unique Key Model)。該模型保證 Key 列的唯一性,插入或更新數據時,新數據會覆蓋具有相同 Key 的舊數據,確保數據記錄為最新。與其他數據模型相比,主鍵模型適用于數據的更新場景,在插入過程中進行主鍵級別的更新覆蓋。如高頻數據更新、數據高效去重以及需要部分列更新的場景。
1.3 實現方式
1.3.1 寫時合并(默認)
數據在寫入時立即合并相同 Key 的記錄,確保存儲的始終是最新數據。寫時合并兼顧查詢和寫入性能,避免多個版本的數據合并,并支持謂詞下推到存儲層。大多數場景推薦使用此模式;
CREATE TABLE IF NOT EXISTS example_tbl_unique
(user_id LARGEINT NOT NULL,user_name VARCHAR(50) NOT NULL,city VARCHAR(20),age SMALLINT,sex TINYINT
)
UNIQUE KEY(user_id, user_name)
DISTRIBUTED BY HASH(user_id) BUCKETS 10
PROPERTIES ("enable_unique_key_merge_on_write" = "true", --指定寫時合并模式"replication_num" = "1"
);
1.3.2 讀時合并(老版本)
在 1.2 版本前,Doris 中的主鍵模型默認使用讀時合并模式,數據在寫入時并不進行合并,以增量的方式被追加存儲,在 Doris 內保留多個版本。查詢或 Compaction 時,會對數據進行相同 Key 的版本合并。讀時合并適合寫多讀少的場景,在查詢是需要進行多個版本合并,謂詞無法下推,可能會影響到查詢速度。
CREATE TABLE IF NOT EXISTS example_tbl_unique_read
(user_id LARGEINT NOT NULL,user_name VARCHAR(50) NOT NULL,city VARCHAR(20),age SMALLINT,sex TINYINT
)
UNIQUE KEY(user_id, user_name)
DISTRIBUTED BY HASH(user_id) BUCKETS 10
PROPERTIES ("enable_unique_key_merge_on_write" = "true", --指定寫時合并模式"replication_num" = "1"
);
1.3.3 數據插入與存儲
INSERT INTO example_tbl_unique_write VALUES
(101, 'Tom', 'BJ', 26, 1),
(101,'cat,'BJ', 26, 1),
(102, 'Jason', 'BJ', 27, 1),
(103, 'Juice', 'SH', 20, 2),
(104, 'Olivia', 'SZ', 22, 2);-- insert into data to update by key
INSERT INTO example_tbl_unique_write VALUES
(101, 'Tom', 'BJ', 27, 1),
(102, 'Jason', 'SH', 28, 1);-- check updated data
SELECT * FROM example_tbl_unique_write;
- 結果如下:
1.4 聚合模型(Aggregate Key Model)
Doris 的聚合模型專為高效處理大規模數據查詢中的聚合操作設計。它通過預聚合數據,減少重復計算,提升查詢性能。聚合模型只存儲聚合后的數據,節省存儲空間并加速查詢。用于對明細數據進行匯總以及不需要查詢原始明細數據。
1.4.1 原理
每一次數據導入會在聚合模型內形成一個版本,在 Compaction 階段進行版本合并,在查詢時會按照主鍵進行數據聚合:
- 數據導入階段:數據按批次導入,每批次生成一個版本,并對相同聚合鍵的數據進行初步聚合(如求和、計數);
- 后臺文件合并階段(Compaction):多個版本文件會定期合并,減少冗余并優化存儲;
- 查詢階段:查詢時,系統會聚合同一聚合鍵的數據,確保查詢結果準確。
1.4.2 建表
CREATE TABLE IF NOT EXISTS example_tbl_agg
(user_id LARGEINT NOT NULL,load_dt DATE NOT NULL,city VARCHAR(20),last_visit_dt DATETIME REPLACE DEFAULT "1970-01-01 00:00:00",cost BIGINT SUM DEFAULT "0",max_dwell INT MAX DEFAULT "0",
)
AGGREGATE KEY(user_id, load_dt, city)
DISTRIBUTED BY HASH(user_id) BUCKETS 10;
PROPERTIES ("replication_num" = "1"
);
1.4.3 聚合函數
聚合方式 | 描述 |
---|---|
SUM | 求和,多行的 Value 進行累加。 |
REPLACE | 替代,下一批數據中的 Value 會替換之前導入過的行中的 Value。 |
MAX | 保留最大值。 |
MIN | 保留最小值。 |
REPLACE_IF_NOT_NULL | 非空值替換。與 REPLACE 的區別在于對 null 值,不做替換。 |
HLL_UNION HLL | 類型的列的聚合方式,通過 HyperLogLog 算法聚合。 |
BITMAP_UNION BITMAP | 類型的列的聚合方式,進行位圖的并集聚合。 |
1.4.4 數據插入與存儲
在聚合表中,數據基于主鍵進行聚合操作。數據插入后及完成聚合操作。
-- 4 rows raw data
INSERT INTO example_tbl_agg VALUES
(101, '2024-11-01', 'BJ', '2024-10-29', 10, 20),
(102, '2024-10-30', 'BJ', '2024-10-29', 20, 20),
(101, '2024-10-30', 'BJ', '2024-10-28', 5, 40),
(101, '2024-10-30', 'SH', '2024-10-29', 10, 20);-- insert into 2 rows
INSERT INTO example_tbl_agg VALUES
(101, '2024-11-01', 'BJ', '2024-10-30', 20, 10),
(102, '2024-11-01', 'BJ', '2024-10-30', 10, 30);-- check the rows of table
SELECT * FROM example_tbl_agg;
+---------+------------+------+---------------------+------+----------------+
| user_id | load_date | city | last_visit_date | cost | max_dwell_time |
+---------+------------+------+---------------------+------+----------------+
| 102 | 2024-10-30 | BJ | 2024-10-29 00:00:00 | 20 | 20 |
| 102 | 2024-11-01 | BJ | 2024-10-30 00:00:00 | 10 | 30 |
| 101 | 2024-10-30 | BJ | 2024-10-28 00:00:00 | 5 | 40 |
| 101 | 2024-10-30 | SH | 2024-10-29 00:00:00 | 10 | 20 |
| 101 | 2024-11-01 | BJ | 2024-10-30 00:00:00 | 30 | 20 |
+---------+------------+------+---------------------+------+----------------+
1.5注意
- 建表時列類型建議
- Key 列必須在所有 Value 列之前。
- 盡量選擇整型類型。因為整型類型的計算和查找效率遠高于字符串。
- 對于不同長度的整型類型的選擇原則,遵循夠用即可。
- 對于 VARCHAR 和 STRING 類型的長度,遵循夠用即可。
1.6自增列
要使用自增列,需要在建表CREATE-TABLE
時為對應的列添加AUTO_INCREMENT屬性。若要手動指定自增列起始值,可以通過建表時AUTO_INCREMENT(start_value)語句指定,如果未指定,則默認起始值為 1。
CREATE TABLE `demo`.`tbl` (`id` BIGINT NOT NULL AUTO_INCREMENT,`value` BIGINT NOT NULL
) ENGINE=OLAP
DUPLICATE KEY(`id`)
DISTRIBUTED BY HASH(`id`) BUCKETS 10
PROPERTIES (
"replication_allocation" = "tag.location.default: 1"
);
2. 數據類型 - Apache Doris
- 數值類型
BOOLEAN
TINYINT
SMALLINT
INT
BIGINT
LARGEINT
FLOAT
DOUBLE
DECIMAL - 日期類型
DATE
DATETIME - 字符串類型
CHAR
VARCHAR
STRING - 半結構類型
ARRAY
MAP
STRUCT
JSON
VARIANT - 聚合類型
HLL
BITMAP
QUANTILE_STATE
AGG_STATE - IP類型
IPv4
IPv6
具體內容可觀看doc文檔
3. 數據壓縮
Doris 采用 列式存儲 模型來組織和存儲數據,這種存儲模型特別適合分析型負載,能夠顯著提高查詢效率。在列式存儲中,表的每一列會獨立存儲,這為壓縮技術的應用提供了便利,從而提高了存儲效率。Doris 提供多種壓縮算法,用戶可以根據工作負載的需求,選擇合適的壓縮方式來優化存儲和查詢性能。
- 選擇合適的壓縮算法需根據工作負載特性:
- 對于 高性能實時分析 場景,推薦使用 LZ4 或 Snappy。
- 對于 存儲效率優先 的場景,推薦使用 ZSTD 或 Zlib。
- 對于需要兼顧速度和壓縮率的場景,可選擇 LZ4F。
- 對于 歸檔或冷數據存儲 場景,建議使用 Zlib 或 LZ4HC。
CREATE TABLE example_table (id INT,name STRING,age INT
)
DUPLICATE KEY(id)
DISTRIBUTED BY HASH(id) BUCKETS 10
PROPERTIES ("compression" = "zstd", --使用zstd壓縮算法"replication_num" = "1"
);
4. 變更表結構(Schema)
用戶可以通過Alter Table
操作來修改 Doris 表的 Schema。Schema 變更主要涉及列的修改和索引的變化。
ALTER TABLE [database.]table alter_clause;
特性 | 輕量級 Schema Change | 重量級 Schema Change |
---|---|---|
執行速度 | 秒級(幾乎實時) | 分鐘級、小時級、天級(依賴表的數據量,數據量越大,執行越慢) |
是否需要數據重寫 | 不需要 | 需要,涉及數據文件的重寫 |
系統性能影響 | 影響較小 | 可能影響系統性能,尤其是在數據轉換過程中 |
資源消耗 | 較低 | 較高,會占用計算資源重新組織數據,過程中涉及到的表的數據占用的存儲空間翻倍。 |
操作類型 | 增加、刪除 Value 列,修改列名,修改 VARCHAR 長度 | 修改列的數據類型、更改主鍵、修改列的順序等 |
- 修改列名稱
ALTER TABLE [database.]table RENAME COLUMN old_column_name new_column_name;
- 添加一列
- 聚合模型如果增加 Value 列,需要指定 agg_type。
首先建表
-- 1.建表
CREATE TABLE IF NOT EXISTS schema_my_table(col1 int,col2 int,col3 int,col4 int SUM,col5 varchar(32) REPLACE DEFAULT "abc"
) AGGREGATE KEY(col1, col2, col3)
DISTRIBUTED BY HASH(col1) BUCKETS 10; #分桶算法:Hash 分桶語法、Random 分桶語法
PROPERTIES ("replication_num" = "1"
);
第二步:向schema_my_table
的 col1 后添加一個 Key 列 key_col
ALTER TABLE example_db.my_table ADD COLUMN key_col INT DEFAULT "0" AFTER col1;
第三步:向 schema_my_table
的 col4 后添加一個 Value 列 value_colSUM
聚合類型
ALTER TABLE example_db.my_table ADD COLUMN value_col INT SUM DEFAULT "0" AFTER col4;
- 非聚合模型(如 DUPLICATE KEY)如果增加 Key 列,需要指定 KEY 關鍵字。
-- 1.建表
CREATE TABLE IF NOT EXISTS test.schema_my_table(col1 int,col2 int,col3 int,col4 int,col5 int
) DUPLICATE KEY(col1, col2, col3)
DISTRIBUTED BY RANDOM BUCKETS 10
PROPERTIES ("replication_num" = "1"
);
第二步:向schema_my_table
的 col1 后添加一個 Key 列 key_co
l
ALTER TABLE schema_my_table ADD COLUMN key_col INT KEY DEFAULT "0" AFTER col1;
第三步:向 schema_my_table
的 col4 后添加一個 Value 列 value_col
ALTER TABLE schema_my_table ADD COLUMN value_col INT DEFAULT "0" AFTER col4;
3. 添加多列
- 聚合模型如果增加 Value 列,需要指定
agg_type
ALTER TABLE example_db.my_table ADD COLUMN (c1 INT DEFAULT "1", c2 FLOAT SUM DEFAULT "0");
- 聚合模型如果增加 Key 列,需要指定 KEY 關鍵字
- 刪除列
ALTER TABLE example_db.my_table DROP COLUMN col4;
- 修改列類型
ALTER TABLE example_db.my_table MODIFY COLUMN col1 BIGINT KEY DEFAULT "1" AFTER col2;
- 重新排序
ALTER TABLE example_db.my_table ORDER BY (k3,k1,k2,k4,v2,v1);
五、測試
5.1 Star Schema Benchmark
Star Schema Benchmark(SSB) 是一個輕量級的數倉場景下的性能測試集。SSB 基于 TPC-H 提供了一個簡化版的星型模型數據集,主要用于測試在星型模型下,多表關聯查詢的性能表現。另外,業界內通常也會將 SSB 打平為寬表模型(以下簡稱:SSB flat),來測試查詢引擎的性能。
# 執行以下腳本下載并編譯 ssb-tools 工具。
./bin/build-ssb-dbgen.sh# 生成 SSB 測試集
./bin/gen-ssb-data.sh -s 100 # 生成 100GB 數據量的表結構# 建表
./bin/create-ssb-tables.sh -s 100# SSB 測試集所有數據導入及 SSB FLAT 寬表數據合成并導入到表里。
./bin/load-ssb-data.sh# 執行SSB查詢
./bin/run-ssb-queries.sh#或者要執行寬表查詢 flat queries
./bin/run-ssb-flat-queries.sh
普通查詢結果
寬表查詢結果