すべてのプロダクト
Search
ドキュメントセンター

E-MapReduce:マテリアライズドビューのクエリリライト

最終更新日:Oct 27, 2025

StarRocks 非同期マテリアライズドビューは、SPJG (select-project-join-group-by) パターンに基づく主流の透過的なクエリリライトアルゴリズムを使用しています。クエリ文を変更することなく、StarRocks はベーステーブルに対するクエリをマテリアライズドビューに対するクエリとして自動的にリライトし、事前計算された結果を使用して計算コストを大幅に削減し、クエリの実行を高速化します。このトピックでは、StarRocks 非同期マテリアライズドビューを使用してクエリをリライトし、高速化する方法について説明します。

シナリオ

StarRocks 非同期マテリアライズドビューのクエリリライト機能は、主に次のシナリオで適用されます。

  • メトリックの事前集約

    高次元データを処理する必要がある場合、マテリアライズドビューを使用して事前集約されたメトリックレイヤーを作成できます。

  • ワイドテーブルの結合

    マテリアライズドビューを使用すると、複雑なシナリオで大規模なワイドテーブルの結合を含むクエリを透過的に高速化できます。

  • レイクハウスアクセラレーション

    外部カタログに基づいてマテリアライズドビューを構築することで、データレイク内のデータを対象とするクエリを簡単に高速化できます。

説明

JDBC カタログテーブル上に構築された非同期マテリアライズドビューは、現在クエリリライトをサポートしていません。

特徴

StarRocks 非同期マテリアライズドビューの自動クエリリライト機能には、次の特徴があります。

  • 強力なデータ整合性: ベーステーブルが StarRocks の内部テーブルである場合、StarRocks はマテリアライズドビューのクエリリライトを通じて得られる結果が、ベーステーブルを直接クエリして得られる結果と一致することを保証できます。

  • ステイルネスリライト: StarRocks はステイルネスリライトをサポートしており、データが頻繁に変更される状況に対応するために、ある程度のデータ有効期限の許容を可能にします。

  • 複数テーブルの結合: StarRocks 非同期マテリアライズドビューは、View Delta Join や Join 派生リライトなどの複雑な結合シナリオを含む、さまざまなタイプの結合をサポートしており、大規模なワイドテーブルを含むクエリシナリオを高速化するために使用できます。

  • 集約リライト: StarRocks は集約操作を含むクエリをリライトして、レポートのパフォーマンスを向上させることができます。

  • ネストされたマテリアライズドビュー: StarRocks は、ネストされたマテリアライズドビューに基づいて複雑なクエリをリライトすることをサポートしており、リライト可能なクエリの範囲を広げます。

  • UNION リライト: UNION リライト機能とマテリアライズドビューパーティションの Time to Live (TTL) を組み合わせることで、ホットデータとコールドデータを分離し、マテリアライズドビューからホットデータを、ベーステーブルから既存データをクエリすることができます。

  • ビューに基づくマテリアライズドビューの構築: ビューに基づいてモデリングが行われるシナリオでクエリを高速化できます。

  • 外部カタログに基づくマテリアライズドビューの構築: この機能を使用して、データレイク内のクエリを高速化できます。

  • 複雑な式のリライト: 式内での関数呼び出しや算術演算をサポートし、複雑な分析や計算の要件に対応します。

制限

単一のマテリアライズドビューのクエリリライト機能に関して、StarRocks には現在、次の制限があります。

  • StarRocks は、rand、random、uuid、sleep などの非決定性関数のリライトをサポートしていません。

  • StarRocks は、ウィンドウ関数のリライトをサポートしていません。

  • マテリアライズドビューの定義文に LIMIT、ORDER BY、UNION、EXCEPT、INTERSECT、MINUS、GROUPING SETS、WITH CUBE、または WITH ROLLUP が含まれている場合、リライトには使用できません。

  • 外部カタログに基づくマテリアライズドビューは、クエリ結果の強力な整合性を保証しません。

  • JDBC カタログテーブル上に構築された非同期マテリアライズドビューは、現在クエリリライトをサポートしていません。

ビューに基づくクエリリライトに関して、StarRocks には現在、次の制限があります。

  • StarRocks は、パーティション UNION リライトをサポートしていません。

  • ビューにランダム関数 (rand()、random()、uuid()、sleep() など) が含まれている場合、クエリリライトはサポートされません。

  • ビューに同じ名前の列が含まれている場合、クエリリライトはサポートされません。同じ名前の列には異なるエイリアスを設定する必要があります。

  • マテリアライズドビューの作成に使用されるビューには、次のデータ型の列が少なくとも 1 つ含まれている必要があります。

    • 整数型

    • 日付と時刻の型

    • 文字列型

Join リライト

StarRocks は、Inner Join、Cross Join、Left Outer Join、Full Outer Join、Right Outer Join、Semi Join、Anti Join など、さまざまなタイプの結合を含むクエリのリライトをサポートしています。

次の例は、結合クエリのリライトを示しています。次のデータベースとベーステーブルを作成します。

CREATE DATABASE IF NOT EXISTS test_db;
USE test_db;
CREATE TABLE customer (
  c_custkey     INT(11)     NOT NULL,
  c_name        VARCHAR(26) NOT NULL,
  c_address     VARCHAR(41) NOT NULL,
  c_city        VARCHAR(11) NOT NULL,
  c_nation      VARCHAR(16) NOT NULL,
  c_region      VARCHAR(13) NOT NULL,
  c_phone       VARCHAR(16) NOT NULL,
  c_mktsegment  VARCHAR(11) NOT NULL
) ENGINE=OLAP
DUPLICATE KEY(c_custkey)
DISTRIBUTED BY HASH(c_custkey) BUCKETS 12;

CREATE TABLE lineorder (
  lo_orderkey         INT(11) NOT NULL,
  lo_linenumber       INT(11) NOT NULL,
  lo_custkey          INT(11) NOT NULL,
  lo_partkey          INT(11) NOT NULL,
  lo_suppkey          INT(11) NOT NULL,
  lo_orderdate        INT(11) NOT NULL,
  lo_orderpriority    VARCHAR(16) NOT NULL,
  lo_shippriority     INT(11) NOT NULL,
  lo_quantity         INT(11) NOT NULL,
  lo_extendedprice    INT(11) NOT NULL,
  lo_ordtotalprice    INT(11) NOT NULL,
  lo_discount         INT(11) NOT NULL,
  lo_revenue          INT(11) NOT NULL,
  lo_supplycost       INT(11) NOT NULL,
  lo_tax              INT(11) NOT NULL,
  lo_commitdate       INT(11) NOT NULL,
  lo_shipmode         VARCHAR(11) NOT NULL
) ENGINE=OLAP
DUPLICATE KEY(lo_orderkey)
DISTRIBUTED BY HASH(lo_orderkey) BUCKETS 48;

上記のベーステーブルに基づいて、次のマテリアライズドビューを作成します。

USE test_db;
CREATE MATERIALIZED VIEW join_mv1
DISTRIBUTED BY HASH(lo_orderkey)
AS
SELECT lo_orderkey, lo_linenumber, lo_revenue, lo_partkey, c_name, c_address
FROM lineorder INNER JOIN customer
ON lo_custkey = c_custkey;

このマテリアライズドビューは、次のクエリをリライトできます。

SELECT lo_orderkey, lo_linenumber, lo_revenue, lo_partkey, c_name, c_address
FROM lineorder INNER JOIN customer
ON lo_custkey = c_custkey;

元のクエリ計画とリライト後の計画は次のとおりです。

image

StarRocks は、算術演算、文字列関数、日付関数、CASE WHEN 式、OR 述語など、複雑な式を含む結合クエリのリライトをサポートしています。たとえば、上記のマテリアライズドビューは次のクエリをリライトできます。

SELECT 
    lo_orderkey, 
    lo_linenumber, 
    (2 * lo_revenue + 1) * lo_linenumber, 
    upper(c_name), 
    substr(c_address, 3)
FROM lineorder INNER JOIN customer
ON lo_custkey = c_custkey;

通常のシナリオに加えて、StarRocks はより複雑な状況での結合クエリのリライトもサポートしています。

Query Delta Join リライト​

Query Delta Join とは、クエリで結合されるテーブルが、マテリアライズドビューで結合されるテーブルのスーパーセットである状況を指します。たとえば、次のクエリはテーブル lineorder、customer、および part を結合します。マテリアライズドビュー join_mv1 が lineorder と customer の結合のみを含む場合、StarRocks は join_mv1 を使用してクエリをリライトできます。

例:

SELECT lo_orderkey, lo_linenumber, lo_revenue, c_name, c_address, p_name
FROM
    lineorder INNER JOIN customer ON lo_custkey = c_custkey
    INNER JOIN part ON lo_partkey = p_partkey;

元のクエリ計画とリライト後の計画は次のとおりです。

image

View Delta Join リライト​

View Delta Join とは、クエリで結合されるテーブルが、マテリアライズドビューで結合されるテーブルのサブセットである状況を指します。この機能は通常、大規模なワイドテーブルを含むシナリオで使用されます。たとえば、Star Schema Benchmark (SSB) のコンテキストでは、すべてのテーブルを結合してマテリアライズドビューを作成し、クエリのパフォーマンスを向上させることができます。テストによると、マテリアライズドビューを通じてクエリを透過的にリライトした後、複数テーブルの結合クエリのパフォーマンスは、対応する大規模なワイドテーブルをクエリするのと同じレベルに達することが示されています。

View Delta Join リライトを有効にするには、マテリアライズドビューがクエリ内のすべての関連テーブルとの 1:1 のカーディナリティを維持する結合 (Cardinality Preservation Joins) を含んでいることを確認する必要があります。制約条件を満たす次の 9 種類の結合は、カーディナリティを維持する結合と見なされ、View Delta Join リライトを有効にするために使用できます。

image

SSB テストを例として、次のデータベースとベーステーブルを作成します。

CREATE DATABASE IF NOT EXISTS test_db;
USE test_db;
CREATE TABLE customer (
  c_custkey         INT(11)       NOT NULL,
  c_name            VARCHAR(26)   NOT NULL,
  c_address         VARCHAR(41)   NOT NULL,
  c_city            VARCHAR(11)   NOT NULL,
  c_nation          VARCHAR(16)   NOT NULL,
  c_region          VARCHAR(13)   NOT NULL,
  c_phone           VARCHAR(16)   NOT NULL,
  c_mktsegment      VARCHAR(11)   NOT NULL
) ENGINE=OLAP
DUPLICATE KEY(c_custkey)
DISTRIBUTED BY HASH(c_custkey) BUCKETS 12
PROPERTIES (
"unique_constraints" = "c_custkey"   -- 一意キーを指定します。
);

CREATE TABLE dates (
  d_datekey          DATE          NOT NULL,
  d_date             VARCHAR(20)   NOT NULL,
  d_dayofweek        VARCHAR(10)   NOT NULL,
  d_month            VARCHAR(11)   NOT NULL,
  d_year             INT(11)       NOT NULL,
  d_yearmonthnum     INT(11)       NOT NULL,
  d_yearmonth        VARCHAR(9)    NOT NULL,
  d_daynuminweek     INT(11)       NOT NULL,
  d_daynuminmonth    INT(11)       NOT NULL,
  d_daynuminyear     INT(11)       NOT NULL,
  d_monthnuminyear   INT(11)       NOT NULL,
  d_weeknuminyear    INT(11)       NOT NULL,
  d_sellingseason    VARCHAR(14)   NOT NULL,
  d_lastdayinweekfl  INT(11)       NOT NULL,
  d_lastdayinmonthfl INT(11)       NOT NULL,
  d_holidayfl        INT(11)       NOT NULL,
  d_weekdayfl        INT(11)       NOT NULL
) ENGINE=OLAP
DUPLICATE KEY(d_datekey)
DISTRIBUTED BY HASH(d_datekey) BUCKETS 1
PROPERTIES (
"unique_constraints" = "d_datekey"   -- 一意キーを指定します。
);

CREATE TABLE supplier (
  s_suppkey          INT(11)       NOT NULL,
  s_name             VARCHAR(26)   NOT NULL,
  s_address          VARCHAR(26)   NOT NULL,
  s_city             VARCHAR(11)   NOT NULL,
  s_nation           VARCHAR(16)   NOT NULL,
  s_region           VARCHAR(13)   NOT NULL,
  s_phone            VARCHAR(16)   NOT NULL
) ENGINE=OLAP
DUPLICATE KEY(s_suppkey)
DISTRIBUTED BY HASH(s_suppkey) BUCKETS 12
PROPERTIES (
"unique_constraints" = "s_suppkey"   -- 一意キーを指定します。
);

CREATE TABLE part (
  p_partkey          INT(11)       NOT NULL,
  p_name             VARCHAR(23)   NOT NULL,
  p_mfgr             VARCHAR(7)    NOT NULL,
  p_category         VARCHAR(8)    NOT NULL,
  p_brand            VARCHAR(10)   NOT NULL,
  p_color            VARCHAR(12)   NOT NULL,
  p_type             VARCHAR(26)   NOT NULL,
  p_size             TINYINT(11)   NOT NULL,
  p_container        VARCHAR(11)   NOT NULL
) ENGINE=OLAP
DUPLICATE KEY(p_partkey)
DISTRIBUTED BY HASH(p_partkey) BUCKETS 12
PROPERTIES (
"unique_constraints" = "p_partkey"   -- 一意キーを指定します。
);

CREATE TABLE lineorder (
  lo_orderdate       DATE          NOT NULL, -- NOT NULL として指定します。
  lo_orderkey        INT(11)       NOT NULL,
  lo_linenumber      TINYINT       NOT NULL,
  lo_custkey         INT(11)       NOT NULL, -- NOT NULL として指定します。
  lo_partkey         INT(11)       NOT NULL, -- NOT NULL として指定します。
  lo_suppkey         INT(11)       NOT NULL, -- NOT NULL として指定します。
  lo_orderpriority   VARCHAR(100)  NOT NULL,
  lo_shippriority    TINYINT       NOT NULL,
  lo_quantity        TINYINT       NOT NULL,
  lo_extendedprice   INT(11)       NOT NULL,
  lo_ordtotalprice   INT(11)       NOT NULL,
  lo_discount        TINYINT       NOT NULL,
  lo_revenue         INT(11)       NOT NULL,
  lo_supplycost      INT(11)       NOT NULL,
  lo_tax             TINYINT       NOT NULL,
  lo_commitdate      DATE          NOT NULL,
  lo_shipmode        VARCHAR(100)  NOT NULL
) ENGINE=OLAP
DUPLICATE KEY(lo_orderdate,lo_orderkey)
PARTITION BY RANGE(lo_orderdate)
(PARTITION p1 VALUES [("0000-01-01"), ("1993-01-01")),
PARTITION p2 VALUES [("1993-01-01"), ("1994-01-01")),
PARTITION p3 VALUES [("1994-01-01"), ("1995-01-01")),
PARTITION p4 VALUES [("1995-01-01"), ("1996-01-01")),
PARTITION p5 VALUES [("1996-01-01"), ("1997-01-01")),
PARTITION p6 VALUES [("1997-01-01"), ("1998-01-01")),
PARTITION p7 VALUES [("1998-01-01"), ("1999-01-01")))
DISTRIBUTED BY HASH(lo_orderkey) BUCKETS 48
PROPERTIES (
"foreign_key_constraints" = "(
    (lo_custkey) REFERENCES customer(c_custkey),
    (lo_partkey) REFERENCES part(p_partkey),
    (lo_suppkey) REFERENCES supplier(s_suppkey)
    )"  -- 外部キー制約を指定します。
);

テーブル lineorder、customer、supplier、part、および dates を結合するマテリアライズドビュー lineorder_flat_mv を作成します。

USE test_db;
CREATE MATERIALIZED VIEW lineorder_flat_mv
DISTRIBUTED BY HASH(LO_ORDERDATE, LO_ORDERKEY) BUCKETS 48
PARTITION BY LO_ORDERDATE
REFRESH MANUAL
PROPERTIES (
    "partition_refresh_number"="1"
)
AS SELECT /*+ SET_VAR(query_timeout = 7200) */     -- リフレッシュのタイムアウトを設定します。
       l.LO_ORDERDATE        AS LO_ORDERDATE,
       l.LO_ORDERKEY         AS LO_ORDERKEY,
       l.LO_LINENUMBER       AS LO_LINENUMBER,
       l.LO_CUSTKEY          AS LO_CUSTKEY,
       l.LO_PARTKEY          AS LO_PARTKEY,
       l.LO_SUPPKEY          AS LO_SUPPKEY,
       l.LO_ORDERPRIORITY    AS LO_ORDERPRIORITY,
       l.LO_SHIPPRIORITY     AS LO_SHIPPRIORITY,
       l.LO_QUANTITY         AS LO_QUANTITY,
       l.LO_EXTENDEDPRICE    AS LO_EXTENDEDPRICE,
       l.LO_ORDTOTALPRICE    AS LO_ORDTOTALPRICE,
       l.LO_DISCOUNT         AS LO_DISCOUNT,
       l.LO_REVENUE          AS LO_REVENUE,
       l.LO_SUPPLYCOST       AS LO_SUPPLYCOST,
       l.LO_TAX              AS LO_TAX,
       l.LO_COMMITDATE       AS LO_COMMITDATE,
       l.LO_SHIPMODE         AS LO_SHIPMODE,
       c.C_NAME              AS C_NAME,
       c.C_ADDRESS           AS C_ADDRESS,
       c.C_CITY              AS C_CITY,
       c.C_NATION            AS C_NATION,
       c.C_REGION            AS C_REGION,
       c.C_PHONE             AS C_PHONE,
       c.C_MKTSEGMENT        AS C_MKTSEGMENT,
       s.S_NAME              AS S_NAME,
       s.S_ADDRESS           AS S_ADDRESS,
       s.S_CITY              AS S_CITY,
       s.S_NATION            AS S_NATION,
       s.S_REGION            AS S_REGION,
       s.S_PHONE             AS S_PHONE,
       p.P_NAME              AS P_NAME,
       p.P_MFGR              AS P_MFGR,
       p.P_CATEGORY          AS P_CATEGORY,
       p.P_BRAND             AS P_BRAND,
       p.P_COLOR             AS P_COLOR,
       p.P_TYPE              AS P_TYPE,
       p.P_SIZE              AS P_SIZE,
       p.P_CONTAINER         AS P_CONTAINER,
       d.D_DATE              AS D_DATE,
       d.D_DAYOFWEEK         AS D_DAYOFWEEK,
       d.D_MONTH             AS D_MONTH,
       d.D_YEAR              AS D_YEAR,
       d.D_YEARMONTHNUM      AS D_YEARMONTHNUM,
       d.D_YEARMONTH         AS D_YEARMONTH,
       d.D_DAYNUMINWEEK      AS D_DAYNUMINWEEK,
       d.D_DAYNUMINMONTH     AS D_DAYNUMINMONTH,
       d.D_DAYNUMINYEAR      AS D_DAYNUMINYEAR,
       d.D_MONTHNUMINYEAR    AS D_MONTHNUMINYEAR,
       d.D_WEEKNUMINYEAR     AS D_WEEKNUMINYEAR,
       d.D_SELLINGSEASON     AS D_SELLINGSEASON,
       d.D_LASTDAYINWEEKFL   AS D_LASTDAYINWEEKFL,
       d.D_LASTDAYINMONTHFL  AS D_LASTDAYINMONTHFL,
       d.D_HOLIDAYFL         AS D_HOLIDAYFL,
       d.D_WEEKDAYFL         AS D_WEEKDAYFL
   FROM lineorder            AS l
       INNER JOIN customer   AS c ON c.C_CUSTKEY = l.LO_CUSTKEY
       INNER JOIN supplier   AS s ON s.S_SUPPKEY = l.LO_SUPPKEY
       INNER JOIN part       AS p ON p.P_PARTKEY = l.LO_PARTKEY
       INNER JOIN dates      AS d ON l.LO_ORDERDATE = d.D_DATEKEY;    

SSB Q2.1 の例は次のとおりです。

USE test_db;
SELECT
    SUM(lo_revenue) AS lo_revenue,
    d_year,
    p_brand
FROM lineorder
    JOIN dates ON lo_orderdate = d_datekey
    JOIN part ON lo_partkey = p_partkey
    JOIN supplier ON lo_suppkey = s_suppkey
WHERE p_category = 'MFGR#12' AND s_region = 'AMERICA'
GROUP BY d_year, p_brand
ORDER BY d_year, p_brand;

SSB Q2.1 は 4 つのテーブルの結合を含みますが、マテリアライズドビュー lineorder_flat_mv と比較して、customer テーブルが欠けています。lineorder_flat_mv では、lineorder INNER JOIN customer は本質的にカーディナリティを維持する結合です。したがって、論理的には、この結合はクエリ結果に影響を与えることなく削除できます。結果として、Q2.1 は lineorder_flat_mv を使用してリライトできます。

元のクエリ計画とリライト後の計画は次のとおりです。

image

同様に、SSB の他のクエリも lineorder_flat_mv を使用して透過的にリライトでき、クエリのパフォーマンスを最適化できます。

Join 派生リライト

Join 派生とは、マテリアライズドビューとクエリの結合タイプが一致しないが、マテリアライズドビューの結合結果がクエリの結合結果を含む状況を指します。

現在、次の 2 つのシナリオがサポートされています。

3 つ以上のテーブルの結合

マテリアライズドビューがテーブル t1 と t2 の間の Left Outer Join、およびテーブル t2 と t3 の間の Inner Join を含むとします。両方の結合条件には、テーブル t2 の列が含まれています。

クエリは、t1 と t2 の間の Inner Join、および t2 と t3 の間の Inner Join を含みます。両方の結合条件には、テーブル t2 の列が含まれています。

この場合、上記のクエリはマテリアライズドビューを通じてリライトできます。これは、マテリアライズドビューでは、まず Left Outer Join が実行され、次に Inner Join が実行されるためです。Left Outer Join は、右側のテーブルに一致がない結果 (つまり、右側のテーブルの列が NULL) を生成します。これらの結果は、Inner Join の実行中にフィルタリングされます。したがって、マテリアライズドビューとクエリは論理的に同等であり、クエリはリライトできます。

たとえば、次のマテリアライズドビュー join_mv5 を作成します。

USE test_db;
CREATE MATERIALIZED VIEW join_mv5
PARTITION BY lo_orderdate
DISTRIBUTED BY hash(lo_orderkey)
PROPERTIES (
  "partition_refresh_number" = "1"
)
AS
SELECT lo_orderkey, lo_orderdate, lo_linenumber, lo_revenue, c_custkey, c_address, p_name
FROM customer LEFT OUTER JOIN lineorder
ON c_custkey = lo_custkey
INNER JOIN part
ON p_partkey = lo_partkey;

join_mv5 は次のクエリをリライトできます。

USE test_db;
SELECT lo_orderkey, lo_orderdate, lo_linenumber, lo_revenue, c_custkey, c_address, p_name
FROM customer INNER JOIN lineorder
ON c_custkey = lo_custkey
INNER JOIN part
ON p_partkey = lo_partkey;

元のクエリ計画とリライト後の計画は次のとおりです。

image

同様に、マテリアライズドビューが t1 INNER JOIN t2 INNER JOIN t3 として定義され、クエリが LEFT OUTER JOIN t2 INNER JOIN t3 である場合、クエリもリライトできます。さらに、このリライト機能は 3 つ以上のテーブルが関与する場合にも適用されます。

2 つのテーブルの結合

2 つのテーブルの結合派生リライトは、次のサブシナリオをサポートします。

image

シナリオ 1 から 9 では、セマンティクスが同等であることを保証するために、リライト結果にフィルター述語を追加する必要があります。たとえば、次のマテリアライズドビューを作成します。

USE test_db;
CREATE MATERIALIZED VIEW join_mv3
DISTRIBUTED BY hash(lo_orderkey)
AS
SELECT lo_orderkey, lo_linenumber, lo_revenue, c_custkey, c_address
FROM lineorder LEFT OUTER JOIN customer
ON lo_custkey = c_custkey;

その後、join_mv3 は次のクエリをリライトでき、クエリ結果は述語 c_custkey IS NOT NULL で補完される必要があります。

USE test_db;
SELECT lo_orderkey, lo_linenumber, lo_revenue, c_custkey, c_address
FROM lineorder INNER JOIN customer
ON lo_custkey = c_custkey;

元のクエリ計画とリライト後の計画は次のとおりです。

image

シナリオ 10 では、Left Outer Join クエリは、右側のテーブルに IS NOT NULL フィルター述語 (=、<>、>、<、<=、>=、LIKE、IN、NOT LIKE、または NOT IN など) を含んでいる必要があります。たとえば、次のマテリアライズドビューを作成します。

USE test_db;
CREATE MATERIALIZED VIEW join_mv4
DISTRIBUTED BY hash(lo_orderkey)
AS
SELECT lo_orderkey, lo_linenumber, lo_revenue, c_custkey, c_address
FROM lineorder INNER JOIN customer
ON lo_custkey = c_custkey;

その後、join_mv4 は次のクエリをリライトできます。ここで、customer.c_address = "Sb4gxKs7" は IS NOT NULL 述語です。

USE test_db;
SELECT lo_orderkey, lo_linenumber, lo_revenue, c_custkey, c_address
FROM lineorder LEFT OUTER JOIN customer
ON lo_custkey = c_custkey
WHERE customer.c_address = "Sb4gxKs7";

元のクエリ計画とリライト後の計画は次のとおりです。

image

集約リライト

StarRocks 非同期マテリアライズドビューの複数テーブル集約クエリリライトは、bitmap_union、hll_union、percentile_union を含むすべての集約関数をサポートしています。たとえば、次のマテリアライズドビューを作成します。

USE test_db;
CREATE MATERIALIZED VIEW agg_mv1
DISTRIBUTED BY hash(lo_orderkey)
AS
SELECT 
  lo_orderkey, 
  lo_linenumber, 
  c_name, 
  sum(lo_revenue) AS total_revenue, 
  max(lo_discount) AS max_discount 
FROM lineorder INNER JOIN customer
ON lo_custkey = c_custkey
GROUP BY lo_orderkey, lo_linenumber, c_name;

このマテリアライズドビューは、次のクエリをリライトできます。

USE test_db;
SELECT
  lo_orderkey, 
  lo_linenumber, 
  c_name, 
  sum(lo_revenue) AS total_revenue, 
  max(lo_discount) AS max_discount 
FROM lineorder INNER JOIN customer
ON lo_custkey = c_custkey
GROUP BY lo_orderkey, lo_linenumber, c_name;

元のクエリ計画とリライト後の計画は次のとおりです。

image

以下では、集約リライト機能が使用できるシナリオについて詳しく説明します。

集約ロールアップリライト

StarRocks は、集約ロールアップによるクエリのリライトをサポートしています。つまり、StarRocks は GROUP BY a,b 句で作成された非同期マテリアライズドビューを使用して、GROUP BY a 句を持つ集約クエリをリライトできます。たとえば、agg_mv1 は次のクエリをリライトできます。

USE test_db;
SELECT 
  lo_orderkey, 
  c_name, 
  sum(lo_revenue) AS total_revenue, 
  max(lo_discount) AS max_discount 
FROM lineorder INNER JOIN customer
ON lo_custkey = c_custkey
GROUP BY lo_orderkey, c_name;

元のクエリ計画とリライト後の計画は次のとおりです。

image

説明

現在、grouping set、grouping set with rollup、および grouping set with cube のリライトはサポートされていません。

一部の集約関数のみが集約ロールアップクエリリライトをサポートしています。次の表は、元のクエリの集約関数と、マテリアライズドビューの構築に使用される集約関数との対応関係を示しています。ビジネスシナリオに基づいて、適切な集約関数を選択してマテリアライズドビューを構築できます。

元のクエリの集約関数

集約ロールアップをサポートするマテリアライズドビュー構築用の集約関数

sum

sum

count

count

min

min

max

max

avg

sum/count

bitmap_union, bitmap_union_count, count(distinct)

bitmap_union

hll_raw_agg, hll_union_agg, ndv, approx_count_distinct

hll_union

percentile_approx, percentile_union

percentile_union

対応する GROUP BY 列のない DISTINCT 集約は、集約ロールアップクエリリライトを使用できません。ただし、StarRocks v3.1 から、DISTINCT 集約関数を持つクエリに GROUP BY 列がなくても、同等の述語がある場合、StarRocks は同等の述語を GROUP BY 定数式に変換できるため、クエリは関連するマテリアライズドビューによってリライトできます。

次の例では、StarRocks はマテリアライズドビュー order_agg_mv1 を使用して、対応するクエリをリライトできます。

USE test_db;
CREATE MATERIALIZED VIEW order_agg_mv1
DISTRIBUTED BY HASH(`order_id`) BUCKETS 12
REFRESH ASYNC START('2022-09-01 10:00:00') EVERY (interval 1 day)
AS
SELECT
    order_date,
    count(distinct client_id) 
FROM order_list 
GROUP BY order_date;


-- Query
USE test_db;
SELECT
    order_date,
    count(distinct client_id) 
FROM order_list WHERE order_date='2023-07-03';

集約プッシュダウン

v3.3.0 から、StarRocks はマテリアライズドビューのクエリリライトのための集約プッシュダウン機能をサポートしています。この機能が有効な場合、クエリ実行中に集約関数が Scan オペレーターにプッシュダウンされ、Join オペレーターが実行される前にマテリアライズドビューによってリライトされます。これにより、結合操作によって引き起こされるデータ拡張が緩和され、クエリのパフォーマンスが向上します。

この機能はデフォルトで無効になっています。有効にするには、システム変数 enable_materialized_view_agg_pushdown_rewrite を true に設定する必要があります。

次の SSB ベースのクエリ SQL1 を高速化する必要があるとします。

-- SQL1
USE test_db;
SELECT 
    LO_ORDERDATE, sum(LO_REVENUE), max(LO_REVENUE), count(distinct LO_REVENUE)
FROM lineorder l JOIN dates d 
ON l.LO_ORDERDATE = d.d_date 
GROUP BY LO_ORDERDATE 
ORDER BY LO_ORDERDATE;

SQL1 は、lineorder テーブル内の集約と、lineorder と dates テーブル間の結合を含みます。集約は lineorder 内で行われ、dates との結合はデータフィルタリングにのみ使用されます。したがって、SQL1 は論理的に次の SQL2 と同等です。

-- SQL2
USE test_db;
SELECT 
    LO_ORDERDATE, sum(sum1), max(max1), bitmap_union_count(bitmap1)
FROM 
 (SELECT
  LO_ORDERDATE,  sum(LO_REVENUE) AS sum1, max(LO_REVENUE) AS max1, bitmap_union(to_bitmap(LO_REVENUE)) AS bitmap1
  FROM lineorder 
  GROUP BY LO_ORDERDATE) l JOIN dates d 
ON l.LO_ORDERDATE = d.d_date 
GROUP BY LO_ORDERDATE 
ORDER BY LO_ORDERDATE;

SQL2 は集約を前倒しにし、結合のデータ量を大幅に削減します。SQL2 のサブクエリに基づいてマテリアライズドビューを作成し、集約プッシュダウンを有効にして集約をリライトし、高速化できます。

-- マテリアライズドビュー mv0 を作成
USE test_db;
CREATE MATERIALIZED VIEW mv0 REFRESH MANUAL AS
SELECT
  LO_ORDERDATE, 
  sum(LO_REVENUE) AS sum1, 
  max(LO_REVENUE) AS max1, 
  bitmap_union(to_bitmap(LO_REVENUE)) AS bitmap1
FROM lineorder 
GROUP BY LO_ORDERDATE;

-- 集約プッシュダウンを有効化
SET enable_materialized_view_agg_pushdown_rewrite=true;

この時点で、SQL1 はマテリアライズドビューを通じてリライトされ、高速化されます。リライトされたクエリは次のとおりです。

USE test_db;
SELECT 
    LO_ORDERDATE, sum(sum1), max(max1), bitmap_union_count(bitmap1)
FROM 
 (SELECT LO_ORDERDATE, sum1, max1, bitmap1 FROM mv0) l JOIN dates d 
ON l.LO_ORDERDATE = d.d_date 
GROUP BY LO_ORDERDATE
ORDER BY LO_ORDERDATE;

集約ロールアップリライトをサポートする一部の集約関数のみがプッシュダウンできることに注意してください。現在、次の集約関数がプッシュダウンをサポートしています。

  • MIN

  • MAX

  • COUNT

  • COUNT DISTINCT

  • SUM

  • BITMAP_UNION

  • HLL_UNION

  • PERCENTILE_UNION

  • BITMAP_AGG

  • ARRAY_AGG_DISTINCT

説明
  • プッシュダウンされた集約関数は、元のセマンティクスと一致するようにロールアップされる必要があります。集約ロールアップの詳細については、「集約ロールアップリライト」をご参照ください。

  • 集約プッシュダウンは、Bitmap または HLL 関数に基づく Count Distinct ロールアップリライトをサポートしています。

  • 集約プッシュダウンは、クエリ内の集約関数を Scan オペレーターの上、Join、Filter、および Where オペレーターの下にプッシュダウンすることのみをサポートしています。

  • 集約プッシュダウンは、単一のテーブル上に構築されたマテリアライズドビューを使用したクエリリライトと高速化のみをサポートしています。

COUNT DISTINCT リライト

StarRocks は、COUNT DISTINCT 計算を BITMAP 型の計算にリライトすることをサポートしており、マテリアライズドビューを使用して高性能で正確な重複排除を可能にします。たとえば、次のマテリアライズドビューを作成します。

USE test_db;
CREATE MATERIALIZED VIEW distinct_mv
DISTRIBUTED BY hash(lo_orderkey)
AS
SELECT lo_orderkey, bitmap_union(to_bitmap(lo_custkey)) AS distinct_customer
FROM lineorder
GROUP BY lo_orderkey;

このマテリアライズドビューは、次のクエリをリライトできます。

USE test_db;
SELECT lo_orderkey, count(distinct lo_custkey) 
FROM lineorder 
GROUP BY lo_orderkey;

ネストされたマテリアライズドビューのリライト

StarRocks は、ネストされたマテリアライズドビューを使用したクエリのリライトをサポートしています。たとえば、次のマテリアライズドビュー join_mv2、agg_mv2、および agg_mv3 を作成します。

USE test_db;
CREATE MATERIALIZED VIEW join_mv2
DISTRIBUTED BY hash(lo_orderkey)
AS
SELECT lo_orderkey, lo_linenumber, lo_revenue, lo_discount, c_name, c_address
FROM lineorder INNER JOIN customer
ON lo_custkey = c_custkey;


CREATE MATERIALIZED VIEW agg_mv2
DISTRIBUTED BY hash(lo_orderkey)
AS
SELECT 
  lo_orderkey, 
  lo_linenumber, 
  c_name, 
  SUM(lo_revenue) AS total_revenue, 
  MAX(lo_discount) AS max_discount 
FROM join_mv2
GROUP BY lo_orderkey, lo_linenumber, c_name;

CREATE MATERIALIZED VIEW agg_mv3
DISTRIBUTED BY hash(lo_orderkey)
AS
SELECT 
  lo_orderkey, 
  SUM(total_revenue) AS total_revenue, 
  MAX(max_discount) AS max_discount 
FROM agg_mv2
GROUP BY lo_orderkey;

それらの関係は次のとおりです。

image

agg_mv3 は次のクエリをリライトできます。

USE test_db;
SELECT 
  lo_orderkey, 
  SUM(lo_revenue) AS total_revenue, 
  MAX(lo_discount) AS max_discount 
FROM lineorder INNER JOIN customer
ON lo_custkey = c_custkey
GROUP BY lo_orderkey;

元のクエリ計画とリライト後の計画は次のとおりです。

image

UNION リライト

述語 UNION リライト

マテリアライズドビューの述語範囲がクエリの述語範囲のサブセットである場合、クエリは UNION 操作を使用してリライトできます。

たとえば、次のマテリアライズドビューを作成します。

USE test_db;
CREATE MATERIALIZED VIEW agg_mv4
DISTRIBUTED BY hash(lo_orderkey)
AS
SELECT 
  lo_orderkey, 
  SUM(lo_revenue) AS total_revenue, 
  MAX(lo_discount) AS max_discount 
FROM lineorder
WHERE lo_orderkey < 300000000
GROUP BY lo_orderkey;

このマテリアライズドビューは、次のクエリをリライトできます。

USE test_db;
SELECT 
  lo_orderkey, 
  SUM(lo_revenue) AS total_revenue, 
  MAX(lo_discount) AS max_discount 
FROM lineorder
GROUP BY lo_orderkey;

元のクエリ計画とリライト後の計画は次のとおりです。

image

ここで、agg_mv4 は lo_orderkey < 300000000 のデータを含み、lo_orderkey >= 300000000 のデータは lineorder テーブルを直接クエリして取得されます。最後に、結果は Union 操作の後に集約され、最終結果が取得されます。

パーティション UNION リライト

パーティション化されたテーブルに基づいてパーティション化されたマテリアライズドビューが作成されたとします。クエリによってスキャンされるパーティション範囲がマテリアライズドビューの最新のパーティション範囲のスーパーセットである場合、クエリは UNION 操作を使用してリライトできます。

たとえば、次のマテリアライズドビュー agg_mv5 を考えます。ベーステーブル lineorder は現在、パーティション p1 から p7 を含み、マテリアライズドビューもパーティション p1 から p7 を含みます。

USE test_db;
CREATE MATERIALIZED VIEW agg_mv5
DISTRIBUTED BY hash(lo_orderkey)
PARTITION BY RANGE(lo_orderdate)(
  START ("1993-01-01") END ("1999-01-01") EVERY (INTERVAL 1 YEAR)
)
REFRESH MANUAL
AS
SELECT 
  lo_orderdate, 
  lo_orderkey, 
  sum(lo_revenue) AS total_revenue, 
  max(lo_discount) AS max_discount 
FROM lineorder
GROUP BY lo_orderdate,lo_orderkey;

lineorder が範囲 [("19990101"), ("20000101")) の新しいパーティション p8 を追加した場合、次のクエリは UNION 操作を使用してリライトできます。

USE test_db;
SELECT 
  lo_orderdate, 
  lo_orderkey, 
  sum(lo_revenue) AS total_revenue, 
  max(lo_discount) AS max_discount 
FROM lineorder
GROUP BY lo_orderdate,lo_orderkey;

元のクエリ計画とリライト後の計画は次のとおりです。

image

上記のように、agg_mv5 はパーティション p1 から p7 のデータを含み、パーティション p8 のデータは lineorder から取得されます。最後に、これら 2 つのデータセットは UNION 操作を使用して結合されます。

ビューに基づくマテリアライズドビューを使用したクエリリライト

v3.1.0 から、StarRocks はビューに基づくマテリアライズドビューの作成をサポートしています。ビューに基づくクエリが SPJG タイプである場合、StarRocks はクエリをインライン展開してからリライトします。デフォルトでは、ビューに対するクエリは自動的にビューのベーステーブルに対するクエリに展開され、その後透過的に照合およびリライトされます。

しかし、実際のシナリオでは、直接展開できない複雑なネストされたビューに基づいてデータをモデル化することがあります。そのため、これらのビューに基づいて作成されたマテリアライズドビューはクエリをリライトできません。このような状況での機能を向上させるため、v3.3.0 から、StarRocks はビューに基づくマテリアライズドビューのクエリリライトロジックを最適化しました。

基本原則​

以前のクエリリライトロジックでは、StarRocks はビューに基づくクエリをビューのベーステーブルを対象とするクエリに展開していました。展開されたクエリの実行計画が SPJG パターンと一致しない場合、マテリアライズドビューはクエリをリライトできませんでした。

この問題に対処するため、StarRocks は新しいオペレーターである LogicalViewScanOperator を導入しました。これにより、実行計画ツリーの構造が簡素化され、クエリを展開する必要がなくなります。これにより、クエリ実行計画ツリーが SPJG パターンを満たす可能性が高まり、クエリリライトが最適化されます。

次の例は、集約サブクエリを含むクエリ、サブクエリ上に構築されたビュー、ビューに基づいて展開されたクエリ、およびビュー上に構築されたマテリアライズドビューを示しています。

-- 元のクエリ
SELECT 
  v1.a,
  t2.b,
  v1.total
FROM(
  SELECT 
    a,
    sum(c) AS total
  FROM t1
  GROUP BY a
) v1
INNER JOIN t2 ON v1.a = t2.a;

-- サブクエリ上に構築されたビュー
CREATE VIEW view_1 AS
SELECT 
  t1.a,
  sum(t1.c) AS total
FROM t1
GROUP BY t1.a;
    
-- ビューに基づくクエリ
SELECT 
  v1.a,
  t2.b,
  v1.total
FROM view_1 v1
JOIN t2 ON v1.a = t2.a;
    
-- ビューに基づくマテリアライズドビュー
CREATE MATERIALIZED VIEW mv1
DISTRIBUTED BY hash(a)
REFRESH MANUAL
AS
SELECT 
  v1.a,
  t2.b,
  v1.total
FROM view_1 v1
JOIN t2 ON v1.a = t2.a;

元のクエリの実行計画は、下の図の左側に示されています。JOIN 内の LogicalAggregateOperator が SPJG パターンと一致しないため、StarRocks はこの場合のクエリリライトをサポートしていません。しかし、サブクエリがビューとして定義されている場合、元のクエリはそのビューを対象とするクエリに展開できます。LogicalViewScanOperator を使用することで、StarRocks は一致しない部分を SPJG パターンに変換し、クエリのリライトを可能にします。

image

設定項目

StarRocks は、デフォルトでビューに基づくマテリアライズドビューのクエリリライトを無効にしています。

この機能を有効にするには、次の変数を設定する必要があります。

SET enable_view_based_mv_rewrite = true;

使用シナリオ​

単一ビューに基づくマテリアライズドビューを使用したクエリリライト

StarRocks は、集約クエリを含む、単一ビューに基づくマテリアライズドビューによるクエリリライトをサポートしています。

たとえば、TPC-H クエリ 18 のために次のビューとマテリアライズドビューを構築できます。

USE test_db;
CREATE VIEW q18_view
AS
SELECT
  c_name,
  c_custkey,
  o_orderkey,
  o_orderdate,
  o_totalprice,
  sum(l_quantity)
FROM
  customer,
  orders,
  lineitem
WHERE
  o_orderkey IN (
    SELECT
      l_orderkey
    FROM
      lineitem
    GROUP BY
      l_orderkey having
        sum(l_quantity) > 315
  )
  AND c_custkey = o_custkey
  AND o_orderkey = l_orderkey
GROUP BY
    c_name,
    c_custkey,
    o_orderkey,
    o_orderdate,
    o_totalprice;

CREATE MATERIALIZED VIEW q18_mv
DISTRIBUTED BY hash(c_custkey, o_orderkey)
REFRESH MANUAL
AS
SELECT * FROM q18_view;

このマテリアライズドビューは、次の 2 つのクエリをリライトできます。

USE test_db;
-- SQL1
EXPLAIN LOGICAL SELECT * FROM q18_view;
+-------------------------------------------------------------------------------------------------------+
| Explain String                                                                                        |
+-------------------------------------------------------------------------------------------------------+
| - Output => [2:c_name, 1:c_custkey, 9:o_orderkey, 10:o_orderdate, 13:o_totalprice, 52:sum]            |
|     - SCAN [q18_mv] => [1:c_custkey, 2:c_name, 52:sum, 9:o_orderkey, 10:o_orderdate, 13:o_totalprice] |
|             MaterializedView: true                                                                    |
|             Estimates: {row: 9, cpu: 486.00, memory: 0.00, network: 0.00, cost: 243.00}               |
|             partitionRatio: 1/1, tabletRatio: 96/96                                                   |
|             1:c_custkey := 60:c_custkey                                                               |
|             2:c_name := 59:c_name                                                                     |
|             52:sum := 64:sum(l_quantity)                                                              |
|             9:o_orderkey := 61:o_orderkey                                                             |
|             10:o_orderdate := 62:o_orderdate                                                          |
|             13:o_totalprice := 63:o_totalprice                                                        |
+-------------------------------------------------------------------------------------------------------+
-- SQL2
EXPLAIN LOGICAL SELECT c_name, sum(`sum(l_quantity)`) FROM q18_view GROUP BY c_name;
+-----------------------------------------------------------------------------------------------------+
| Explain String                                                                                      |
+-----------------------------------------------------------------------------------------------------+
| - Output => [2:c_name, 59:sum]                                                                      |
|     - AGGREGATE(GLOBAL) [2:c_name]                                                                  |
|             Estimates: {row: 9, cpu: 306.00, memory: 306.00, network: 0.00, cost: 1071.00}          |
|             59:sum := sum(59:sum)                                                                   |
|         - EXCHANGE(SHUFFLE) [2]                                                                     |
|                 Estimates: {row: 9, cpu: 30.60, memory: 0.00, network: 30.60, cost: 306.00}         |
|             - AGGREGATE(LOCAL) [2:c_name]                                                           |
|                     Estimates: {row: 9, cpu: 61.20, memory: 30.60, network: 0.00, cost: 244.80}     |
|                     59:sum := sum(52:sum)                                                           |
|                 - SCAN [q18_mv] => [2:c_name, 52:sum]                                               |
|                         MaterializedView: true                                                      |
|                         Estimates: {row: 9, cpu: 306.00, memory: 0.00, network: 0.00, cost: 153.00} |
|                         partitionRatio: 1/1, tabletRatio: 96/96                                     |
|                         2:c_name := 60:c_name                                                       |
|                         52:sum := 65:sum(l_quantity)                                                |
+-----------------------------------------------------------------------------------------------------+

ビューに基づくマテリアライズドビューを使用した JOIN クエリのリライト

StarRocks は、ビュー間またはビューとテーブル間の JOIN を含むクエリのリライトをサポートしており、JOIN の上での集約も含まれます。

たとえば、次のビューとマテリアライズドビューを作成できます。

USE test_db;
CREATE VIEW view_1
AS
SELECT
  c_custkey,
  c_name,
  c_address,
  c_city,
  c_nation,
  c_region
FROM customer;

CREATE VIEW view_2
AS
SELECT
  lo_orderkey,
  lo_linenumber,
  lo_custkey,
  lo_partkey,
  lo_revenue,
  lo_supplycost
FROM lineorder;

CREATE MATERIALIZED VIEW join_mv
DISTRIBUTED BY hash(lo_orderkey)
REFRESH MANUAL
AS
SELECT
  v1.c_custkey,
  v1.c_name,
  v1.c_address,
  v2.lo_orderkey,
  v2.lo_linenumber,
  v2.lo_revenue
FROM view_1 v1
JOIN view_2 v2
ON v1.c_custkey = v2.lo_custkey;

このマテリアライズドビューは、次のクエリをリライトできます。

USE test_db;
SELECT
  v1.c_custkey,
  v1.c_name,
  v1.c_address,
  v2.lo_orderkey,
  v2.lo_linenumber,
  v2.lo_revenue
FROM view_1 v1
JOIN view_2 v2
ON v1.c_custkey = v2.lo_custkey;

ビューのマテリアライズドビューに基づく外部テーブルクエリのリライト

外部カタログの外部テーブル上にビューを作成し、これらのビューに基づいてマテリアライズドビューを構築してクエリをリライトできます。使用方法は内部テーブルと同様です。

外部カタログに基づくマテリアライズドビューを使用したクエリリライト

StarRocks は、Hive Catalog、Hudi Catalog、Iceberg Catalog、および Paimon Catalog に基づいて外部データソース上に非同期マテリアライズドビューを構築することをサポートし、透過的なクエリリライトをサポートしています。外部カタログに基づくマテリアライズドビューは、ほとんどのクエリリライト機能をサポートしていますが、次の制限があります。

  • Hudi、Paimon、および JDBC Catalog に基づいて作成されたマテリアライズドビューは、Union リライトをサポートしていません。

  • Hudi、Paimon、および JDBC Catalog に基づいて作成されたマテリアライズドビューは、View Delta Join リライトをサポートしていません。

  • Hudi および JDBC Catalog に基づいて作成されたマテリアライズドビューは、パーティションの増分更新をサポートしていません。

テキストベースのマテリアライズドビューリライト

v3.3.0 から、StarRocks はテキストベースのマテリアライズドビューリライトをサポートし、クエリリライトの能力を大幅に拡張しました。

基本原則​

テキストベースのマテリアライズドビューリライトを実装するために、StarRocks はクエリ (またはそのサブクエリ) の抽象構文木とマテリアライズドビュー定義の抽象構文木を比較します。両方が一致する場合、StarRocks はマテリアライズドビューに基づいてクエリをリライトできます。テキストベースのマテリアライズドビューリライトはシンプルで効率的であり、従来の SPJG タイプのマテリアライズドビュークエリリライトと比較して制限が少なくなっています。この機能を適切に使用することで、クエリのパフォーマンスを大幅に向上させることができます。

テキストベースのマテリアライズドビューリライトは、SPJG タイプのオペレーターだけでなく、Union、Window、Order、Limit、CTE などのオペレーターもサポートしています。

設定項目

設定名

デフォルト値

説明

enable_materialized_view_text_match_rewrite

true

テキストベースのマテリアライズドビューリライトを有効にするかどうかを制御するために使用されます。この機能はデフォルトで有効です。これを false に設定すると、この機能を手動で無効にできます。

enable_materialized_view_text_based_rewrite

true

非同期マテリアライズドビューを作成する際に抽象構文木を構築するかどうかを制御するために使用されます。この機能はデフォルトで有効です。これを false に設定すると、システムレベルでテキストベースのマテリアライズドビューリライトが無効になります。

materialized_view_subuqery_text_match_max_count

4

サブクエリがマテリアライズドビュー定義と一致するかどうかをシステムが比較する最大回数を制御するために使用されます。デフォルト値は 4 です。この値を増やすと、オプティマイザーが消費する時間も増加します。

説明

マテリアライズドビューが適時性 (データ整合性) の要件を満たしている場合にのみ、テキストベースのクエリリライトに使用できます。マテリアライズドビューを作成する際に、プロパティ query_rewrite_consistency を通じて整合性チェックルールを手動で設定できます。

シナリオ​

次の条件を満たすクエリはリライトできます。

  • 元のクエリがマテリアライズドビューの定義と一致している。

  • 元のクエリのサブクエリがマテリアライズドビューの定義と一致している。

従来の SPJG タイプのマテリアライズドビュークエリリライトと比較して、テキストベースのマテリアライズドビューリライトは、多層集約など、より複雑なクエリをサポートします。

説明
  • 照合する必要があるクエリを元のクエリのサブクエリにカプセル化することをお勧めします。

  • マテリアライズドビューの定義や元のクエリのサブクエリに ORDER BY 句をカプセル化しないでください。そうしないと、クエリはリライトできません。これは、サブクエリ内の ORDER BY 句がデフォルトで削除されるためです。

たとえば、次のマテリアライズドビューを構築できます。

USE test_db;
CREATE MATERIALIZED VIEW mv1 REFRESH MANUAL AS
SELECT 
  user_id, 
  count(1) 
FROM (
  SELECT 
    user_id, 
    time, 
    bitmap_union(to_bitmap(tag_id)) AS a
  FROM user_tags 
  GROUP BY 
    user_id, 
    time) t
GROUP BY user_id;

このマテリアライズドビューは、次の 2 つのクエリをリライトできます。

USE test_db;
-- SQL1
SELECT 
  user_id, 
  count(1) 
FROM (
  SELECT 
    user_id, 
    time, 
    bitmap_union(to_bitmap(tag_id)) AS a
  FROM user_tags 
  GROUP BY 
    user_id, 
    time) t
GROUP BY user_id;

-- SQL2
SELECT count(1)
FROM
(
    SELECT 
      user_id, 
      count(1) 
    FROM (
      SELECT 
        user_id, 
        time, 
        bitmap_union(to_bitmap(tag_id)) AS a
      FROM user_tags 
      GROUP BY 
        user_id, 
        time) t
    GROUP BY user_id
)m;

ただし、このマテリアライズドビューは、ORDER BY 句を含む次のクエリをリライトできません。

USE test_db;
SELECT 
  user_id, 
  count(1) 
FROM (
  SELECT 
    user_id, 
    time, 
    bitmap_union(to_bitmap(tag_id)) AS a
  FROM user_tags 
  GROUP BY 
    user_id, 
    time) t
GROUP BY user_id
ORDER BY user_id;

マテリアライズドビューのクエリリライトの設定

次のセッション変数を通じて、非同期マテリアライズドビューのクエリリライトを設定できます。

変数

デフォルト値

説明

enable_materialized_view_union_rewrite

true

マテリアライズドビューの Union リライトを有効にするかどうかを指定します。

enable_rule_based_materialized_view_rewrite

true

主に単一テーブルのクエリリライトを処理するために使用される、ルールベースのマテリアライズドビュークエリリライト機能を有効にするかどうかを指定します。

nested_mv_rewrite_max_level

3

クエリリライトに使用できるネストされたマテリアライズドビューの最大レイヤー数。型: INT。値の範囲: [1, +∞)。値 1 は、ベーステーブルに基づいて作成されたマテリアライズドビューのみがクエリリライトに使用できることを示します。

クエリリライトが有効かどうかの確認

EXPLAIN 文を使用して、対応するクエリ計画を表示できます。OlapScanNode 項目の下の TABLE に対応する非同期マテリアライズドビュー名が表示されている場合、クエリが非同期マテリアライズドビューに基づいてリライトされたことを示します。

USE test_db;
EXPLAIN SELECT
    order_id, sum(goods.price) AS total 
    FROM order_list INNER JOIN goods 
    ON goods.item_id1 = order_list.item_id2 
    GROUP BY order_id;
+------------------------------------+
| Explain String                     |
+------------------------------------+
| PLAN FRAGMENT 0                    |
|  OUTPUT EXPRS:1: order_id | 8: sum |
|   PARTITION: RANDOM                |
|                                    |
|   RESULT SINK                      |
|                                    |
|   1:Project                        |
|   |  <slot 1> : 9: order_id        |
|   |  <slot 8> : 10: total          |
|   |                                |
|   0:OlapScanNode                   |
|      TABLE: order_mv               |
|      PREAGGREGATION: ON            |
|      partitions=1/1                |
|      rollup: order_mv              |
|      tabletRatio=0/12              |
|      tabletList=                   |
|      cardinality=3                 |
|      avgRowSize=4.0                |
|      numNodes=0                    |
+------------------------------------+
20 rows in set (0.01 sec)

クエリリライトの無効化

StarRocks は、デフォルトで Default Catalog に基づいて作成された非同期マテリアライズドビューのクエリリライトを有効にします。セッション変数 enable_materialized_view_rewrite を false に設定することで、この機能を無効にできます。

外部カタログに基づいて作成された非同期マテリアライズドビューの場合、ALTER MATERIALIZED VIEW を通じてマテリアライズドビューのプロパティ force_external_table_query_rewrite を false に設定することで、この機能を無効にできます。