兼顧高效能與低成本,淺析 Apache Doris 非同步物化檢視原理及典型場景

SelectDB技术团队發表於2024-11-20

在現代化的資料分析場景中,資料量以指數級速度快速膨脹,分析維度在不斷擴充套件,查詢邏輯的複雜度也在日益增加。從效能角度考慮,在承擔高併發查詢的壓力下,秒級別甚至更快的響應速度已成為基本需求。同時,面對有限的計算資源,成本及效能如何平衡,嚴格的資源管控也顯得尤為重要。

物化檢視作為一種有效的解決方案,兼顧了檢視的靈活性和物理表的高效能。它可以預先計算並儲存查詢結果集,從而在查詢請求到達時直接從物化檢視中獲取結果,而無需重新執行查詢語句。這種機制有效提升了查詢效能,降低了重複執行查詢的開銷,成為企業加速資料處理、精細控制成本關鍵策略之一。

Apache Doris 物化檢視進行了支援。早期版本中,Doris 支援同步物化檢視;從 2.1 版本開始,正式引入非同步物化檢視,並在 3.0 版本中完善了這一功能 正文開始之前,我們先了解同步和非同步物化檢視的區別:

同步和非同步物化檢視的區別.png

使用者在使用 Apach Doris 過程中,可以根據場景需求選擇適合的物化檢視。同步物化檢視更適合對查詢延遲敏感的場景,而非同步物化檢視則更適合以批次方式進行分析的場景。具體來說:

  • 同步物化檢視:當基礎表更新時,物化檢視會實時同步更新,保證查詢結果的即時準確性,適用於資料更新較少、對查詢響應要求較高的場景。
  • 非同步物化檢視:當基礎表更新時,物化檢視透過定期更新保持資料最終一致,可減少頻繁更新帶來的效能影響,適用於更新不頻繁、批次更新或對實時性要求不高的分析場景。

透過前文,我們已基本瞭解同步及非同步物化檢視的區別及適配場景。本文將重點介紹 Doris 非同步物化檢視的特性及應用。

同步物化檢視的使用可參考官網文件

非同步物化檢視原理淺析

01 支援全量和分割槽增量重新整理

不同於同步物化檢視的實時增量重新整理機制,非同步物化檢視支援全量重新整理和分割槽增量重新整理兩種機制,以保證資料的最終一致性:

  • 全量重新整理:計算並重新整理物化檢視定義 SQL 的所有資料。適合在資料量較小或資料架構發生變化時使用,在對實時性要求不高的場景下可進行定期重新整理。
  • 分割槽增量重新整理:當物化檢視的基表分割槽資料發生變化時,可以識別並僅重新整理變化的分割槽,無需重新整理整個物化檢視,相比全量/實時重新整理顯著減少了計算和儲存開銷。重新整理時會先計算要需要重新整理的分割槽列表,然後拆分成多個 Insert Overwrite 語句順序執行,可指定每次 Insert Overwrite 重新整理的分割槽數量。該方式適用於大資料量場景,尤其是分割槽表頻繁變化且對實時性要求較高的場景。
參考文件

02 支援資源管控與可觀測性

物化檢視的構建及重新整理是一個計算密集型的過程,因此,對該過程進行資源管控和監測至關重要。這可以效避免資源競爭,從而提升查詢速度、最佳化系統效能及穩定性。

在資源管控上, Apache Doris 支援透過workload_group進行資源管理。透過配置workload_group以限制物化檢視構建或重新整理能夠使用的最大系統資源。比如,在建立物化檢視時,支援設定workload_group屬性,以確保物化檢視構建僅使用對應的系統資源,不會影響正常的查詢操作。

在可觀測性上, Doris 不僅支援檢視物化檢視後設資料資訊,也支援檢視物化檢視重新整理任務的 Job 配置詳情、物化檢視重新整理進度以及對應workload_group資源消耗情況,幫助使用者更好的理解和管理物化檢視。

當物化檢視進行重新整理時,系統會根據 Job 配置自動啟動一個任務 Task 例項。可執行下方命令,實時檢視和監控這一任務的狀態。

select * from tasks("type"="mv") where MvName = 'mv_name' order by CreateTime desc;

參考文件:

TASKS

MV_INFOS

Doris 支援透過 Workload 系統表對叢集工作負載進行分析,詳情見工作負載分析

03 支援全面的透明改寫能力

透明改寫指在處理查詢時,可自動對使用者的 SQL 進行最佳化及改寫,提高查詢效能及執行效率,降低計算成本。改寫通常對使用者不可見,無需干預改寫過程。

Doris 非同步物化檢視採用基於 SPJG(SELECT-PROJECT-JOIN-GROUP-BY)模式的透明改寫演算法。該演算法能夠分析 SQL 的結構資訊,自動尋找合適的物化檢視進行透明改寫,並選擇最優的物化檢視來響應查詢 SQL。

Doris 提供了豐富且全面的透明改寫能力:

  • 支援 Join 型別的改寫,並支援 Join 衍生改寫。當查詢和物化檢視的 Join 的型別不一致時,可以透過在 Join 外部新增補償 where 條件來實現透明的改寫。
  • 支援聚合改寫,包括多維聚合函式 GROUPING SETS、ROLLUP、CUBE 的改寫,並支援查詢包含聚合、物化不包含聚合的改寫。
  • 支援巢狀物化檢視的改寫,在複雜的查詢加速場景下,可以藉助巢狀物化檢視進行極致加速。
  • 支援分割槽補償改寫,當分割槽物化檢視部分分割槽失效,可透過 Union All 基表補全資料。

目前,僅新最佳化器支援物化檢視的透明改寫。從 2.1.5 版本開始,透明改寫預設開啟,2.1.5 前的版本使用透明改寫能力,需要手動開啟如下開關。

-- 開啟透明改寫,預設不開啟,自2.1.5開始,預設開啟
SET enable_materialized_view_rewrite = true;
透明改寫能力詳情見文件

非同步物化檢視典型使用場景

01 查詢加速,提高併發,減少資源消耗

在 BI 報表場景或其他加速場景中,使用者對於查詢響應時間較為敏感,通常要求能夠秒級別返回結果。而查詢通常涉及多張表先進行 Join 計算、再聚合計算,該過程會消耗大量計算資源,並且有時難以保證時效性。對此,非同步物化檢視能夠很好應對,它不僅支援直接查詢,也支援透明改寫,最佳化器會依據改寫演算法和代價模型,自動選擇最優的物化檢視來響應請求。

未使用物化檢視的原始查詢:

如下所示對每個月各地區和國家的訂單數量和利潤進行分析。由於涉及多表連線,該查詢消耗了大量資源,並且查詢延遲較高。

SELECT 
    n_name,
    r_name,
    date_trunc(o.o_orderdate, 'month') as month,
    count(distinct o.o_orderkey) as order_count,
    sum(l.l_extendedprice * (1 - l.l_discount)) as revenue
FROM orders o
JOIN lineitem l ON o.o_orderkey = l.l_orderkey
JOIN customer c ON o.o_custkey = c.c_custkey
JOIN nation n ON c.c_nationkey = n.n_nationkey
JOIN region r ON n.n_regionkey = r.r_regionkey
GROUP BY n_name, r_name, month;

使用非同步物化檢視進行查詢加速:

1)構建如下物化檢視,對使用者、月份、地區、國家進行初步聚合

CREATE MATERIALIZED VIEW sales_agg_mv 
BUILD IMMEDIATE REFRESH AUTO ON MANUAL 
DISTRIBUTED BY RANDOM BUCKETS 12
PROPERTIES ('replication_num' = '1') 
AS
SELECT 
    n_name,
    r_name,
    date_trunc(o_orderdate, 'month') as month,
    bitmap_union(to_bitmap(o_orderkey)) as order_count,
    sum(l_extendedprice * (1 - l_discount)) as net_revenue,
    sum(l_quantity) as total_quantity
FROM orders o
JOIN lineitem l ON o.o_orderkey = l.l_orderkey
JOIN customer c ON o.o_custkey = c.c_custkey
JOIN nation n ON c.c_nationkey = n.n_nationkey
JOIN region r ON n.n_regionkey = r.r_regionkey
GROUP BY n_name, r_name, month;

2)透過透明改寫,原始查詢將被最佳化器自動改寫為以下語句:

SELECT 
    n_name,
    r_name,
    month,
    bitmap_union_count(order_count) as order_count,
    sum(net_revenue) as revenue
FROM sales_agg_mv
GROUP BY  
n_name, r_name, month;

由此可見,使用者在不修改原 SQL 的情況下,Doris 會自動選擇最優的物化檢視來響應查詢,這極大提高了查詢效能,減少了資源消耗,並提升了併發處理能力。

為更直觀展示加速效果,我們以 TPCH 資料的 Schema 為例,測試物化檢視加速效果。

  • 資料規模:總資料量是 100G
  • 節點:FE 和 BE 為單節點
  • CPU : 至強 E5-2686V4,36C
  • 記憶體:128G DDR3
  • 硬碟:SSD 固態 2T

查詢加速,提高併發,減少資源消耗.png

從效能對比結果可知,透明改寫查詢相比普通查詢能夠顯著提升查詢效能。在大多數查詢場景中,透明改寫查詢響應時間較普通查詢降低了 99%

02 簡化 ETL 流程,提升開發效率

資料分析工作往往需要對多表進行連線和聚合,這一過程通常涉及複雜且頻繁重複的查詢。這類查詢可能引發查詢延遲高或資源消耗大的問題。然而,如果採用非同步物化檢視構建資料分層模型,則可以很好避免該問題。

接下來,透過 TPC-H 資料集說明非同步物化檢視在資料建模中的應用,以分析每月各地區和國家的訂單數量和利潤為例:

原始查詢(未使用物化檢視):

SELECT 
    n_name,
    date_trunc(o.o_orderdate, 'month') as month,
    count(distinct o.o_orderkey) as order_count,
    sum(l.l_extendedprice * (1 - l.l_discount)) as revenue
FROM orders o
JOIN lineitem l ON o.o_orderkey = l.l_orderkey
JOIN customer c ON o.o_custkey = c.c_custkey
JOIN nation n ON c.c_nationkey = n.n_nationkey
JOIN region r ON n.n_regionkey = r.r_regionkey
GROUP BY n_name, month;

使用非同步物化檢視分層建模:

1)構建 DWD 層(明細資料),處理訂單明細寬表

CREATE MATERIALIZED VIEW dwd_order_detail 
BUILD IMMEDIATE REFRESH AUTO ON COMMIT 
DISTRIBUTED BY RANDOM BUCKETS 16
PROPERTIES ('replication_num' = '1') 
AS
select 
    o.o_orderkey,
    o.o_custkey,
    o.o_orderstatus,
    o.o_totalprice,
    o.o_orderdate,
    c.c_name,
    c.c_nationkey,
    n.n_name as nation_name,
    r.r_name as region_name,
    l.l_partkey,
    l.l_quantity,
    l.l_extendedprice,
    l.l_discount,
    l.l_tax
from orders o
join customer c on o.o_custkey = c.c_custkey
join nation n on c.c_nationkey = n.n_nationkey
join region r on n.n_regionkey = r.r_regionkey
join lineitem l on o.o_orderkey = l.l_orderkey;

2)構建 DWS 層(彙總資料),進行每日訂單彙總

CREATE MATERIALIZED VIEW dws_daily_sales 
BUILD IMMEDIATE REFRESH AUTO ON COMMIT 
DISTRIBUTED BY RANDOM BUCKETS 16
PROPERTIES ('replication_num' = '1') 
AS
select 
    date_trunc(o_orderdate, 'month') as month,
    nation_name,
    region_name,
    bitmap_union(to_bitmap(o_orderkey)) as order_count,
    sum(l_extendedprice * (1 - l_discount)) as net_revenue
from dwd_order_detail
group by 
    date_trunc(o_orderdate, 'month'),
    nation_name,
    region_name;

3)使用物化檢視最佳化查詢如下:

SELECT 
    nation_name,
    month,
    bitmap_union_count(order_count),
    sum(net_revenue) as revenue
FROM dws_daily_sales
GROUP BY nation_name, month;

從上可知,非同步物化檢視運用在資料分層建模之後,查詢語句變得更加簡潔,響應耗時從幾十秒縮短至秒級別:

簡化 ETL 流程,提升開發效率.png

在 DWD 和 DWS 層的構建中,物化檢視透過自動化的資料排程和重新整理機制,簡化了傳統 ETL 的複雜性,顯著提升了整體資料開發效率;同時,它支援觸發式排程,提供更高的建模時效性和資料可見性。此外,基於物化檢視分層建模,可大幅簡化複雜查詢邏輯,減少因重複計算帶來的額外開銷,從而有效提升系統整體吞吐量。

03 結合湖倉一體,加速外表查詢

在現代化的資料架構中,企業通常會採用湖倉一體設計,以平衡資料的儲存成本與查詢效能。在這種架構下,經常會遇到兩個關鍵挑戰:

  • 查詢效能受限:頻繁查詢資料湖中的資料時,可能會受到網路延遲和第三方服務的影響,從而導致查詢延遲,進而影響使用者體驗。
  • 資料分層建模的複雜性:在資料湖到實時數倉的資料流轉和轉換過程中,通常需要複雜的 ETL 流程,這增加了維護成本和開發難度

使用 Doris 非同步物化檢視,可以很好的應對上述挑戰:

  • 透明改寫加速查詢:將常用的資料湖查詢結果物化到 Doris 內部儲存,採用透明改寫可有效提升查詢效能。
  • 簡化分層建模:支援基於資料湖中的表建立物化檢視,實現從資料湖到實時數倉的便捷轉換,極大簡化了資料建模流程。

如下,以 Hive 示例說明:

1)基於 Hive 建立 Catalog,使用 TPC-H 資料集

CREATE CATALOG hive_catalog PROPERTIES (
    'type'='hms',
    -- hive meta store 地址
    'hive.metastore.uris' = 'thrift://172.21.0.1:7004'
);

2)基於 Hive Catalog 建立物化檢視

-- 物化檢視只能在 internal 的 catalog 上建立, 切換到內部 catalog
switch internal;
create database hive_mv_db;
use hive_mv_db;

CREATE MATERIALIZED VIEW external_hive_mv
        BUILD IMMEDIATE REFRESH AUTO ON MANUAL
        DISTRIBUTED BY RANDOM BUCKETS 12
        PROPERTIES ('replication_num' = '1')
AS
SELECT
  n_name,
  o_orderdate,
  sum(l_extendedprice * (1 - l_discount)) AS revenue
FROM
  customer,
  orders,
  lineitem,
  supplier,
  nation,
  region
WHERE
  c_custkey = o_custkey
  AND l_orderkey = o_orderkey
  AND l_suppkey = s_suppkey
  AND c_nationkey = s_nationkey
  AND s_nationkey = n_nationkey
  AND n_regionkey = r_regionkey
  AND r_name = 'ASIA'
GROUP BY
n_name,
o_orderdate;

3)執行如下的查詢,透過透明改寫自動使用物化檢視加速查詢。

SELECT
  n_name,
  sum(l_extendedprice * (1 - l_discount)) AS revenue
FROM
  customer,
  orders,
  lineitem,
  supplier,
  nation,
  region
WHERE
  c_custkey = o_custkey
  AND l_orderkey = o_orderkey
  AND l_suppkey = s_suppkey
  AND c_nationkey = s_nationkey
  AND s_nationkey = n_nationkey
  AND n_regionkey = r_regionkey
  AND r_name = 'ASIA'
  AND o_orderdate >= DATE '1994-01-01'
  AND o_orderdate < DATE '1994-01-01' + INTERVAL '1' YEAR
GROUP BY
n_name
ORDER BY
revenue DESC;

使用注意:Doris 暫無法感知除 Hive 外的其他外表資料變更。當外表資料不一致時,使用物化檢視可能出現資料不一致的情況。以下開關表示:參與透明改寫的物化檢視是否允許包含外表,預設false。如接受資料不一致或者透過定時重新整理來保證外表資料一致性,可以將此開關設定成true

-- 設定包含外表的物化檢視是否可用於透明改寫,預設不允許,如果可以接受資料不一致或者可以自行保證資料一致,
-- 可以開啟
SET materialized_view_rewrite_enable_contain_external_table = true;

下表為使用非同步物化檢視前後的效能差異,使用透明改寫之後,查詢速度較之前提升約 93 倍。

結合湖倉一體,加速外表查詢.png

04 提升寫入效率,減少資源競爭

1. 靈活重新整理策略,避免資源競爭

在高吞吐的資料寫入的場景中,系統效能的穩定性與資料處理的高效性同樣重要。透過非同步物化檢視靈活的重新整理策略,使用者可以根據具體場景選擇合適的重新整理方式,從而降低寫入壓力,避免資源爭搶。

使用同步物化檢視時,由於重新整理策略的限制,通常只能進行高頻的實時更新。雖然能夠保障時效性,但面對高頻、大規模的匯入操作時,極易出現系統資源持續佔用,影響資料處理效能。

相比之下,非同步物化檢視提供了手動觸發、觸發式、週期性觸發三種靈活的重新整理策略。使用者可以根據場景需求差異,選擇合適的重新整理策略。當基表資料變更時,不會立即觸發物化檢視重新整理,延遲重新整理有利於降低資源壓力,有效避免寫入資源爭搶。

如下所示,選擇的重新整理方式為定時重新整理,每 2 小時重新整理一次。當orderslineitem 匯入資料時,不會立即觸發物化檢視重新整理。

CREATE MATERIALIZED VIEW common_schedule_join_mv
BUILD IMMEDIATE REFRESH AUTO ON SCHEDULE EVERY 2 HOUR
DISTRIBUTED BY RANDOM BUCKETS 16
PROPERTIES  ('replication_num' = '1')
AS 
SELECT 
  l_linestatus, 
  l_extendedprice * (1 - l_discount),
  o_orderdate, 
  o_shippriority 
FROM 
  orders 
  LEFT JOIN lineitem ON l_orderkey = o_orderkey;

2. 透明改寫匯入 SQL,提升匯入效率

透明改寫能夠對查詢 SQL 的改寫,實現了查詢加速,同時也能對匯入 SQL 進行改寫,從而提升匯入效率。

從 2.1.6 版本開始,當物化檢視和基表資料強一致時,可對 DML 操作如 Insert Into 或者 Insert Overwrite 進行透明改寫,這對於資料匯入場景的效能提升有顯著效果。

A. 建立 Insert Into 資料的目標表

CREATE TABLE IF NOT EXISTS target_table  (
  orderdate      DATE NOT NULL,
  shippriority   INTEGER NOT NULL,
  linestatus     CHAR(1) NOT NULL,
  sale           DECIMALV3(15,2) NOT NULL
)
DUPLICATE KEY(orderdate, shippriority)
DISTRIBUTED BY HASH(shippriority) BUCKETS 3
PROPERTIES (
  "replication_num" = "1"
);

B. common\_schedule\_join_mv:

CREATE MATERIALIZED VIEW common_schedule_join_mv
BUILD IMMEDIATE REFRESH AUTO ON SCHEDULE EVERY 2 HOUR
DISTRIBUTED BY RANDOM BUCKETS 16
PROPERTIES  ('replication_num' = '1')
AS 
SELECT 
  l_linestatus, 
  l_extendedprice * (1 - l_discount),
  o_orderdate, 
  o_shippriority 
FROM 
  orders 
  LEFT JOIN lineitem ON l_orderkey = o_orderkey;

未經改寫的匯入語句如下:

INSERT INTO target_table 
SELECT 
  o_orderdate, 
  o_shippriority,
  l_linestatus, 
  l_extendedprice * (1 - l_discount)
FROM 
  orders 
  LEFT JOIN lineitem ON l_orderkey = o_orderkey;

經過透明改寫後,語句如下:

INSERT INTO target_table 
SELECT *
FROM common_schedule_join_mv;

需要注意的是:如果 DML 操作的是無法感知資料變更的外表,透明改寫可能導致基表最新資料無法實時匯入目標表。如果使用者可以接受資料不一致或能夠自行保證資料一致性,可以開啟如下開關

-- DML 時,當物化檢視存在無法實時感知資料的外表時,是否開啟基於結構資訊的物化檢視透明改寫,預設關閉
SET enable_dml_materialized_view_rewrite_when_base_table_unawareness = true;

最佳使用實踐

01 高效複用物化檢視,平衡查詢與構建成本

查詢加速需權衡物化檢視的構建成本與查詢效能。物化檢視越通用,透明改寫後的效能提升效果越低;而越符合需求的定製化物化檢視,效能提升效果越好,但定製化物化檢視很難被複用。這有違於高效能、低成本的基本原則。

那麼,如何複用物化檢視,能夠更好的平衡查詢與構建成本?為便於大家提高工作效率,我們整理了一些構建物化檢視的基本原則:

  • Join:提取查詢中使用的公共表連線模式構建物化檢視,以節省連線計算。
  • Aggregate:儘量使用低基數字段作為維度,確保聚合後的資料量小於原查詢。
  • Filter:若查詢中頻繁對同一欄位進行過濾,可在物化檢視中新增相應的 Filter。
  • Calculate Expressions :對於效能消耗較大的表示式(如複雜的 CASE WHEN 和字串處理函式),可在物化檢視中定義這些表示式。
  • 固定查詢:如果查詢語句固定且對效能要求極高,可以直接使用原查詢語句構建物化檢視。

舉例說明,以如下查詢為例,我們分別建立不同的物化檢視:

SELECT 
  l_linestatus, 
  sum(
    l_extendedprice * (1 - l_discount)
  ) AS revenue, 
  o_orderdate, 
  o_shippriority 
FROM 
  orders 
  LEFT JOIN lineitem ON l_orderkey = o_orderkey 
WHERE 
  o_orderdate <= DATE '1997-05-01' 
  AND o_orderdate >= DATE '1996-05-15' 
GROUP BY 
  l_linestatus, 
  o_orderdate, 
  o_shippriority;

common\_join\_mv:

CREATE MATERIALIZED VIEW common_join_mv
BUILD IMMEDIATE REFRESH AUTO ON MANUAL
DISTRIBUTED BY RANDOM BUCKETS 2
PROPERTIES  ('replication_num' = '1')
AS 
SELECT 
  l_linestatus, 
  l_extendedprice * (1 - l_discount),
  o_orderdate, 
  o_shippriority 
FROM 
  orders 
  LEFT JOIN lineitem ON l_orderkey = o_orderkey;

target\_agg\_mv:

CREATE MATERIALIZED VIEW target_agg_mv
BUILD IMMEDIATE REFRESH AUTO ON MANUAL
DISTRIBUTED BY RANDOM BUCKETS 2
PROPERTIES  ('replication_num' = '1')
AS 
SELECT 
  l_linestatus, 
  sum(
    l_extendedprice * (1 - l_discount)
  ) AS revenue, 
  o_orderdate, 
  o_shippriority 
FROM 
  orders 
  LEFT JOIN lineitem ON l_orderkey = o_orderkey 
GROUP BY 
  l_linestatus, 
  o_orderdate, 
  o_shippriority;

以上兩個物化檢視均可進行透明改寫。從通用性來看,common_join_mv 更具優勢,適用於更廣泛的透明改寫場景。然而,在透明改寫後的效能表現上,target_agg_mv 則表現更佳,原因是其能夠提前對部分資料進行聚合。

因此,在效能要求較高的場景中,建議構建定製的物化檢視;而在效能要求不那麼嚴格的情況下,可以選擇構建更通用的物化檢視。

02 支援分割槽物化檢視,節省重新整理資源

從前文介紹可知,非同步物化檢視提供了全量和分割槽增量的重新整理策略。因此,當物化檢視基表的分割槽資料發生變化時,使用分割槽增量重新整理可自動識別出物化檢視對應變化的分割槽,並僅重新整理這些分割槽,從而實現分割槽增量重新整理,而無需重新整理整個物化檢視,節省重新整理資源。

當滿足以下條件時,可以建立分割槽物化檢視:

  • 物化檢視的基表資料量較大,並且基表為分割槽表
  • 除分割槽表外,物化檢視使用的其他表不經常發生變化
  • 物化檢視的定義 SQL 和分割槽欄位符合分割槽推導的要求,即滿足分割槽增量更新的條件。詳細要求可參考:CREATE-ASYNC-MATERIALIZED-VIEW
  • 物化檢視的分割槽數不超過 1000

以下方示例:

  CREATE TABLE IF NOT EXISTS lineitem (
    l_orderkey INTEGER NOT NULL, 
    l_partkey INTEGER NOT NULL, 
    l_suppkey INTEGER NOT NULL, 
    l_linenumber INTEGER NOT NULL, 
    l_ordertime DATETIME NOT NULL, 
    l_quantity DECIMALV3(15, 2) NOT NULL, 
    l_extendedprice DECIMALV3(15, 2) NOT NULL, 
    l_discount DECIMALV3(15, 2) NOT NULL, 
    l_tax DECIMALV3(15, 2) NOT NULL, 
    l_returnflag CHAR(1) NOT NULL, 
    l_linestatus CHAR(1) NOT NULL, 
    l_shipdate DATE NOT NULL, 
    l_commitdate DATE NOT NULL, 
    l_receiptdate DATE NOT NULL, 
    l_shipinstruct CHAR(25) NOT NULL, 
    l_shipmode CHAR(10) NOT NULL, 
    l_comment VARCHAR(44) NOT NULL
  ) DUPLICATE KEY(
    l_orderkey, l_partkey, l_suppkey, 
    l_linenumber
  ) PARTITION BY RANGE(l_ordertime) (
    FROM 
      ('2024-05-01') TO ('2024-06-30') INTERVAL 1 DAY
  ) DISTRIBUTED BY HASH(l_orderkey) BUCKETS 3 PROPERTIES ("replication_num" = "1"); 
  
    insert into lineitem values      
     (1, 2, 3, 4, '2024-05-01 01:45:05', 5.5, 6.5, 0.1, 8.5, 'o', 'k', '2024-05-01', '2024-05-01', '2024-05-01', 'a', 'b', 'yyyyyyyyy'),    
     (1, 2, 3, 4, '2024-05-15 02:35:05', 5.5, 6.5, 0.15, 8.5, 'o', 'k', '2024-05-15', '2024-05-15', '2024-05-15', 'a', 'b', 'yyyyyyyyy'),     
     (2, 2, 3, 5, '2024-05-25 08:30:06', 5.5, 6.5, 0.2, 8.5, 'o', 'k', '2024-05-25', '2024-05-25', '2024-05-25', 'a', 'b', 'yyyyyyyyy'),     
     (3, 4, 3, 6, '2024-06-02 09:25:07', 5.5, 6.5, 0.3, 8.5, 'o', 'k', '2024-06-02', '2024-06-02', '2024-06-02', 'a', 'b', 'yyyyyyyyy'),     
     (4, 4, 3, 7, '2024-06-15 13:20:09', 5.5, 6.5, 0, 8.5, 'o', 'k', '2024-06-15', '2024-06-15', '2024-06-15', 'a', 'b', 'yyyyyyyyy'),     
     (5, 5, 6, 8, '2024-06-25 15:15:36', 5.5, 6.5, 0.12, 8.5, 'o', 'k', '2024-06-25', '2024-06-25', '2024-06-25', 'a', 'b', 'yyyyyyyyy'),     
     (5, 5, 6, 9, '2024-06-29 21:10:52', 5.5, 6.5, 0.1, 8.5, 'o', 'k', '2024-06-30', '2024-06-30', '2024-06-30', 'a', 'b', 'yyyyyyyyy'),     
     (5, 6, 5, 10, '2024-06-03 22:05:50', 7.5, 8.5, 0.1, 10.5, 'k', 'o', '2024-06-03', '2024-06-03', '2024-06-03', 'c', 'd', 'xxxxxxxxx');     
  
   CREATE TABLE IF NOT EXISTS partsupp (
    ps_partkey INTEGER NOT NULL, 
    ps_suppkey INTEGER NOT NULL, 
    ps_availqty INTEGER NOT NULL, 
    ps_supplycost DECIMALV3(15, 2) NOT NULL, 
    ps_comment VARCHAR(199) NOT NULL
  ) DUPLICATE KEY(ps_partkey, ps_suppkey) DISTRIBUTED BY HASH(ps_partkey) BUCKETS 3 PROPERTIES ("replication_num" = "1"); 
  
  
      insert into partsupp values     
      (2, 3, 9, 10.01, 'supply1'),     
      (4, 3, 9, 10.01, 'supply2'),     
      (5, 6, 9, 10.01, 'supply3'),     
      (6, 5, 10, 11.01, 'supply4');

orders表的 o_ordertime欄位為分割槽欄位,型別為 DATETIME,按照天進行分割槽。以下查詢基於“天”粒度進行,查詢粒度較粗。

SELECT 
  l_linestatus, 
  sum(
    l_extendedprice * (1 - l_discount)
  ) AS revenue, 
  ps_partkey 
FROM 
  lineitem 
  LEFT JOIN partsupp ON l_partkey = ps_partkey 
  and l_suppkey = ps_suppkey 
WHERE 
  date_trunc(l_ordertime, 'day') <= DATE '2024-05-25' 
  AND date_trunc(l_ordertime, 'day') >= DATE '2024-05-05' 
GROUP BY 
  l_linestatus, 
  ps_partkey;

為避免物化檢視每次重新整理時分割槽數量過多而消耗過多資源,物化檢視的分割槽粒度可以與基表 orders 一致,按“天”進行分割槽。物化檢視的定義如下,以上查詢可以透過透明改寫命中此物化檢視。

CREATE MATERIALIZED VIEW rollup_partition_mv 
BUILD IMMEDIATE REFRESH AUTO ON MANUAL 
partition by(order_date) 
DISTRIBUTED BY RANDOM BUCKETS 2 
PROPERTIES ('replication_num' = '1') 
AS 
SELECT 
  l_linestatus, 
  sum(
    l_extendedprice * (1 - l_discount)
  ) AS revenue, 
  ps_partkey, 
  date_trunc(l_ordertime, 'day') as order_date 
FROM 
  lineitem 
  LEFT JOIN partsupp ON l_partkey = ps_partkey 
  and l_suppkey = ps_suppkey 
GROUP BY 
  l_linestatus, 
  ps_partkey, 
  date_trunc(l_ordertime, 'day');

注意:如果使用者修改的資料涉及多個分割槽,物化檢視的重新整理將會影響到多個分割槽,這可能導致重新整理效能下降,類似於全量重新整理的效果。

結束語

以上就是對 Apache Doris 非同步物化檢視的詳細介紹。其功能強大,支援全量及分割槽增量重新整理機制,具備資源管控與可觀測性,透明改寫能力更加全面。在查詢加速、資料建模、高吞吐寫入、湖倉一體等典型場景中,使用非同步物化檢視均有顯著的效能及資源利用率提升。

未來,我們將不斷完善物化檢視的構建,提升透明改寫的穩定性與準確性,實施精細化的資源控制,並增強構建和重新整理的監控手段。同時,計劃擴充套件透明改寫的功能,逐步支援物化檢視的智慧管理,降低使用者使用物化檢視的成本,為使用者提供更優質的使用體驗。

相關文章