Doris 查詢太慢?要不要試試這幾項(xiàng)加速技術(shù)
Apache Doris 作為一款現(xiàn)代化的 MPP 分析型數(shù)據(jù)庫,其查詢性能一直是核心優(yōu)勢。本文將深入探討 Doris 的查詢加速技術(shù)體系,從執(zhí)行引擎優(yōu)化到緩存機(jī)制,從 Join 策略到資源管理,結(jié)合具體場景和代碼示例,全面解析如何最大化 Doris 的查詢性能。

一、執(zhí)行引擎:Pipeline 與 PipelineX
1. 傳統(tǒng)執(zhí)行引擎的瓶頸
傳統(tǒng)火山模型(Volcano Model)中,每個操作符(Operator)通過 Next() 方法逐條拉取數(shù)據(jù),導(dǎo)致 CPU 緩存利用率低、函數(shù)調(diào)用開銷大:
// 傳統(tǒng)火山模型偽代碼
while (row = child_op->Next()) {
    processed_row = process(row);
    emit(processed_row);
}2. Pipeline 執(zhí)行引擎原理
Pipeline 引擎通過向量化執(zhí)行和批處理技術(shù)優(yōu)化:
-- 啟用 Pipeline 引擎
set enable_pipeline_engine = true;
-- 查看執(zhí)行計(jì)劃是否使用 Pipeline
EXPLAIN SELECT ... FROM ...;核心優(yōu)勢:
- 批處理:一次處理 1024 行數(shù)據(jù)(默認(rèn)批大?。?/li>
 - 向量化:利用 SIMD 指令加速計(jì)算
 - 流水線并行:多線程并行執(zhí)行不同階段
 
3. PipelineX 引擎增強(qiáng)
PipelineX 在 Pipeline 基礎(chǔ)上增加了本地shuffle優(yōu)化:
-- 啟用 PipelineX
set enable_pipeline_x_engine = true;
-- 查看執(zhí)行計(jì)劃中的 LocalExchange 算子
EXPLAIN SELECT COUNT(*) FROM large_table GROUP BY region;適用場景:
- 大數(shù)據(jù)量聚合查詢
 - 需要本地預(yù)聚合的復(fù)雜查詢
 
二、查詢緩存:SQL Cache
1. 緩存機(jī)制原理
SQL Cache 基于查詢文本和參數(shù)精確匹配:
-- 啟用 SQL Cache
SET enable_sql_cache = true;
-- 查看緩存命中率
SHOW VARIABLES LIKE '%sql_cache%';緩存命中條件:
- 查詢文本完全一致(包括空格和大小寫)
 - 參數(shù)值相同
 - 涉及表數(shù)據(jù)未變更
 
2. 緩存優(yōu)化實(shí)踐
-- 1. 使用參數(shù)化查詢提高緩存命中率
-- 低效方式(每次參數(shù)不同都生成新緩存項(xiàng))
SELECT*FROM orders WHERE user_id =1001;
SELECT*FROM orders WHERE user_id =1002;
-- 高效方式(使用視圖或CTE)
CREATEVIEW user_orders AS
SELECT*FROM orders WHERE user_id = ${user_id};
-- 2. 控制緩存粒度
-- 小結(jié)果集查詢適合緩存
SELECTCOUNT(*) FROM orders WHEREdate='2023-10-01';
-- 大結(jié)果集查詢禁用緩存
SET enable_sql_cache =false;
SELECT*FROM large_table;三、Join 優(yōu)化策略
1. Bucket Shuffle Join
通過數(shù)據(jù)分布預(yù)定位減少網(wǎng)絡(luò)傳輸:
-- 創(chuàng)建表時指定分布鍵
CREATE TABLE orders (
    order_id BIGINT,
    user_id BIGINT,
    ...
) DISTRIBUTED BY HASH(user_id) BUCKETS 32;
CREATE TABLE users (
    user_id BIGINT,
    ...
) DISTRIBUTED BY HASH(user_id) BUCKETS 32;
-- 查詢自動使用 Bucket Shuffle Join
EXPLAIN 
SELECT o.*, u.name 
FROM orders o 
JOIN users u ON o.user_id = u.user_id;優(yōu)化效果:
- 減少 90%+ 的網(wǎng)絡(luò)數(shù)據(jù)傳輸
 - 適用于大表 Join 大表場景
 
2. Colocation Join
共址 Join 保證關(guān)聯(lián)數(shù)據(jù)在同一節(jié)點(diǎn):
-- 創(chuàng)建同組(Group)的表
CREATE TABLE table_a (
    k1 INT,
    ...
) DISTRIBUTED BY HASH(k1) BUCKETS 32
PROPERTIES (
    "colocation_with" = "group1"
);
CREATE TABLE table_b (
    k1 INT,
    ...
) DISTRIBUTED BY HASH(k1) BUCKETS 32
PROPERTIES (
    "colocation_with" = "group1"
);
-- 查詢自動使用 Colocation Join
EXPLAIN 
SELECT a.*, b.*
FROM table_a a 
JOIN table_b b ON a.k1 = b.k1;適用場景:
- 頻繁 Join 的維度表
 - 數(shù)據(jù)量相對穩(wěn)定的表
 
3. Runtime Filter
動態(tài)過濾減少 Join 數(shù)據(jù)量:
-- 啟用 Runtime Filter
SET enable_runtime_filter = true;
-- 查看執(zhí)行計(jì)劃中的 Runtime Filter
EXPLAIN 
SELECT o.* 
FROM orders o 
JOIN (SELECT user_id FROM vip_users) v 
ON o.user_id = v.user_id;優(yōu)化類型:
- IN Filter:適用于高基數(shù)字段
 - Bloom Filter:適用于超高基數(shù)字段
 - MinMax Filter:適用于數(shù)值類型
 
-- 手動調(diào)整 Runtime Filter 類型
SET runtime_filter_type = "BLOOM_FILTER";四、高效去重技術(shù)
1. BITMAP 精準(zhǔn)去重
-- 創(chuàng)建表時使用 BITMAP 類型
CREATE TABLE user_actions (
    user_id BIGINT,
    action_date DATE,
    actions BITMAP BITMAP_UNION
) AGGREGATE KEY(user_id, action_date);
-- 數(shù)據(jù)導(dǎo)入
INSERT INTO user_actions VALUES
(1001, '2023-10-01', to_bitmap(101)),
(1001, '2023-10-01', to_bitmap(102)),
(1001, '2023-10-01', to_bitmap(101));
-- 查詢?nèi)ブ亟Y(jié)果
SELECT
    user_id,
    action_date,
    bitmap_union_count(actions) AS unique_actions
FROM user_actions
GROUPBY user_id, action_date;性能對比:
-- 傳統(tǒng) COUNT(DISTINCT) 方式
SELECT user_id, COUNT(DISTINCT action_id) 
FROM user_actions_raw 
GROUP BY user_id;
-- BITMAP 方式(快 5-10 倍)
SELECT user_id, bitmap_union_count(actions) 
FROM user_actions 
GROUP BY user_id;2. HLL 近似去重
-- 創(chuàng)建表時使用 HLL 類型
CREATE TABLE page_views (
    page_id INT,
    view_date DATE,
    users HLL HLL_UNION
) AGGREGATE KEY(page_id, view_date);
-- 數(shù)據(jù)導(dǎo)入
INSERT INTO page_views VALUES
(1001, '2023-10-01', hll_hash(1001)),
(1001, '2023-10-01', hll_hash(1002)),
(1001, '2023-10-01', hll_hash(1001));
-- 查詢近似去重結(jié)果
SELECT
    page_id,
    view_date,
    hll_union_agg(users) AS approx_unique_users
FROM page_views
GROUPBY page_id, view_date;誤差控制:
-- 設(shè)置 HLL 精度(默認(rèn) 12,精度越高誤差越?。?SET hll_precision = 16;五、高并發(fā)點(diǎn)查優(yōu)化
1. 行存與列存結(jié)合
-- 創(chuàng)建 Unique 模型表(自動行存)
CREATE TABLE orders (
    order_id BIGINT,
    user_id BIGINT,
    amount DECIMAL(10,2),
    status VARCHAR(20)
) UNIQUE KEY(order_id)
DISTRIBUTED BY HASH(order_id) BUCKETS 32;
-- 查詢自動使用行存優(yōu)化
SELECT * FROM orders WHERE order_id = 1000001;2. PreparedStatement 優(yōu)化
// Java 代碼示例
String sql = "SELECT * FROM orders WHERE order_id = ?";
try (PreparedStatement stmt = connection.prepareStatement(sql)) {
    stmt.setInt(1, 1000001);
    ResultSet rs = stmt.executeQuery();
    // 處理結(jié)果
}優(yōu)化效果:
- 減少 SQL 解析開銷
 - 提高執(zhí)行計(jì)劃復(fù)用率
 
3. 行緩存配置
-- 啟用行緩存
SET enable_row_cache = true;
-- 調(diào)整行緩存大?。J(rèn) 2MB)
SET row_cache_mem_limit = "50MB";
-- 查看緩存命中率
SHOW BACKENDS;
-- 然后訪問 BE 的 metrics 頁面查看 row_cache_hit_rate六、TOPN 查詢優(yōu)化
1. 優(yōu)化原理
TOPN 查詢通過提前終止和堆排序優(yōu)化:
-- 傳統(tǒng)方式(全排序后取前N)
SELECT * FROM orders ORDER BY amount DESC LIMIT 10;
-- 優(yōu)化方式(使用 TopN 算子)
EXPLAIN 
SELECT * FROM orders ORDER BY amount DESC LIMIT 10;2. 配置優(yōu)化
-- 啟用 TopN 優(yōu)化
SET enable_topn_opt = true;
-- 調(diào)整 TopN 緩存大小
SET topn_cache_size = 1024;七、查詢分析與調(diào)優(yōu)
1. 獲取執(zhí)行 Profile
-- 執(zhí)行查詢并獲取 Profile
SET show_profile = true;
SELECT COUNT(*) FROM large_table GROUP BY region;
-- 查看詳細(xì) Profile
SHOW PROFILE;關(guān)鍵指標(biāo)分析:
- ScanNode:數(shù)據(jù)掃描時間
 - HashJoinNode:Join 階段耗時
 - AggregationNode:聚合計(jì)算時間
 - ExchangeNode:數(shù)據(jù)傳輸時間
 
2. 查詢分析示例
-- 示例:分析慢查詢
-- 1. 獲取查詢ID
SHOW PROCESSLIST;
-- 2. 獲取指定查詢的 Profile
SHOW PROFILE FOR QUERY 'query_id';
-- 3. 分析 Profile 中的瓶頸
-- 例如發(fā)現(xiàn) ScanNode 耗時過長:
ScanNode:
- RowsRead: 100000000
- BytesRead: 2GB
- TotalTime: 5.2s
- IOTime: 4.8s  # IO 瓶頸
-- 優(yōu)化方案:增加緩存或優(yōu)化存儲八、資源管理與隔離
1. Workload Group 資源隔離
-- 創(chuàng)建資源組
CREATE WORKLOAD GROUP "analytics"
PROPERTIES (
    "cpu_limit" = "50%",
    "memory_limit" = "30%",
    "concurrency_limit" = "10"
);
-- 創(chuàng)建資源組
CREATE WORKLOAD GROUP "etl"
PROPERTIES (
    "cpu_limit" = "30%",
    "memory_limit" = "50%",
    "concurrency_limit" = "5"
);
-- 將用戶綁定到資源組
CREATEUSER'analyst'@'%' IDENTIFIED BY'password'
PROPERTIES ("workload_group" = "analytics");
CREATEUSER'etl_user'@'%' IDENTIFIED BY'password'
PROPERTIES ("workload_group" = "etl");2. 查詢優(yōu)先級管理
-- 設(shè)置查詢優(yōu)先級
SET QUERY_PRIORITY = 'HIGH';
-- 在資源組中配置優(yōu)先級
ALTER WORKLOAD GROUP "analytics"
SET PROPERTIES ("query_priority" = "HIGH");九、綜合優(yōu)化案例
1. 電商訂單分析場景
-- 1. 表設(shè)計(jì)優(yōu)化
CREATE TABLE orders (
    order_id BIGINT,
    user_id BIGINT,
    order_date DATE,
    amount DECIMAL(10,2),
    status VARCHAR(20),
    region VARCHAR(20),
    INDEX idx_user (user_id) USING BITMAP,
    INDEX idx_date (order_date)
) DUPLICATE KEY(order_id)
PARTITIONBYRANGE(order_date) (
    PARTITION p202301 VALUES LESS THAN ('2023-02-01'),
    PARTITION p202302 VALUES LESS THAN ('2023-03-01')
)
DISTRIBUTED BY HASH(order_id) BUCKETS 32;
-- 2. 查詢優(yōu)化示例
-- 查詢:各區(qū)域月度訂單統(tǒng)計(jì)
SELECT
    region,
    DATE_TRUNC('month', order_date) ASmonth,
    COUNT(DISTINCT order_id) AS order_count,
    SUM(amount) AS total_amount
FROM orders
WHERE order_date BETWEEN'2023-01-01'AND'2023-12-31'
GROUPBY region, DATE_TRUNC('month', order_date)
ORDERBY region, month;
-- 優(yōu)化措施:
-- a. 分區(qū)裁剪(自動)
-- b. 使用 BITMAP 索引加速 COUNT(DISTINCT)
-- c. 聚合下推(自動)2. 實(shí)時監(jiān)控儀表盤場景
-- 1. 創(chuàng)建物化視圖
CREATE MATERIALIZED VIEW mv_user_stats
REFRESH ASYNC EVERY'1 HOUR'
ASSELECT
    user_id,
    COUNT(*) AS order_count,
    SUM(amount) AS total_amount,
    MAX(order_date) AS last_order_date
FROM orders
GROUPBY user_id;
-- 2. 查詢物化視圖
SELECT*FROM mv_user_stats 
WHERE user_id =1001;
-- 3. 監(jiān)控物化視圖狀態(tài)
SHOW MATERIALIZED VIEWS;十、優(yōu)秀實(shí)踐總結(jié)
(1) 執(zhí)行引擎選擇:
- 通用查詢啟用 enable_pipeline_engine = true
 - 復(fù)雜聚合查詢啟用 enable_pipeline_x_engine = true
 
(2) Join 優(yōu)化策略:
- 優(yōu)先使用 Bucket Shuffle Join
 - 頻繁 Join 的表使用 Colocation Join
 - 大表 Join 小表使用 Runtime Filter
 
(3) 去重技術(shù)選擇:
- 精準(zhǔn)去重使用 BITMAP
 - 大數(shù)據(jù)集近似去重使用 HLL
 
(4) 點(diǎn)查優(yōu)化組合:
- Unique 模型 + PreparedStatement + 行緩存
 
(5) 資源管理:
- 關(guān)鍵業(yè)務(wù)使用高優(yōu)先級 Workload Group
 - 監(jiān)控內(nèi)存使用,避免 OOM
 
(6) 查詢分析:
- 定期分析慢查詢 Profile
 - 關(guān)注 IO、CPU 和內(nèi)存瓶頸
 
通過綜合運(yùn)用這些優(yōu)化技術(shù),Apache Doris 可以在大多數(shù)分析場景下實(shí)現(xiàn)亞秒級響應(yīng),滿足高并發(fā)、低延遲的查詢需求。實(shí)際應(yīng)用中,建議結(jié)合業(yè)務(wù)特點(diǎn)和數(shù)據(jù)特征,選擇最適合的優(yōu)化組合方案。















 
 
 



 
 
 
 