メインコンテンツまでスキップ

Data lake query acceleration

マテリアライズドビューを使用したデータレイクのクエリ高速化

このトピックでは、StarRocks の非同期マテリアライズドビューを使用して、データレイク内のクエリパフォーマンスを最適化する方法について説明します。

StarRocks には、データレイクのクエリ機能が組み込まれており、レイク内のデータの探索的なクエリや分析に非常に効果的です。ほとんどのシナリオでは、データキャッシュ により、リモートストレージの揺れや大量の I/O 処理によるパフォーマンスの低下を回避するブロックレベルのファイルキャッシングが提供されます。

しかし、データレイクからのデータを使用して複雑で効率的なレポートを構築し、これらのクエリをさらに高速化する場合、パフォーマンスの課題が発生する場合があります。非同期マテリアライズドビューを使用することで、レイク上のレポートやデータアプリケーションの高い並行性とクエリパフォーマンスを実現できます。

概要

StarRocks は、Hive カタログ、Iceberg カタログ、Hudi カタログなどの外部カタログを基にした非同期マテリアライズドビューの構築をサポートしています。外部カタログベースのマテリアライズドビューは、次のシナリオで特に有用です。

  • データレイクレポートの透過的な高速化データレイクのレポートのクエリパフォーマンスを確保するために、データエンジニアは通常、レポートの高速化層の構築ロジックをデータアナリストと密に連携して調査する必要があります。高速化層の更新が必要な場合、構築ロジック、処理スケジュール、クエリ文を更新する必要があります。マテリアライズドビューのクエリ書き換え機能により、レポートの高速化をユーザーに透過的かつ感知されないように実現できます。遅いクエリが特定された場合、データエンジニアは遅いクエリのパターンを分析し、必要に応じてマテリアライズドビューを作成することができます。アプリケーション側のクエリは、マテリアライズドビューによってインテリジェントに書き換えられ、クエリパフォーマンスが迅速に改善されます。これにより、ビジネスアプリケーションやクエリ文のロジックを変更することなく、クエリパフォーマンスを大幅に向上させることができます。
  • 過去のデータに関連するリアルタイムデータの増分計算ビジネスアプリケーションには、StarRocks ネイティブテーブルのリアルタイムデータとデータレイクの過去のデータを関連付けて増分計算する必要がある場合があります。このような場合、マテリアライズドビューは簡単な解決策を提供できます。たとえば、リアルタイムのファクトテーブルが StarRocks のネイティブテーブルであり、ディメンションテーブルがデータレイクに格納されている場合、外部データソースのテーブルとネイティブテーブルを関連付けるマテリアライズドビューを構築することで、簡単に増分計算を実行することができます。
  • メトリックレイヤーの迅速な構築メトリックの計算と処理は、データの高次元性を扱う際に課題になることがあります。マテリアライズドビューを使用することで、データの事前集計とロールアップを実行することができます。さらに、マテリアライズドビューは自動的にリフレッシュされるため、メトリックの計算の複雑さがさらに軽減されます。

マテリアライズドビュー、データキャッシュ、およびStarRocksのネイティブテーブルは、クエリパフォーマンスを大幅に向上させるための効果的な方法です。次の表は、これらの方法の主な違いを比較しています:

 

データキャッシュ

マテリアライズドビュー

ネイティブテーブル

データの読み込みと更新

クエリ実行時にデータキャッシュが自動的にトリガされます。

更新タスクが自動的にトリガされます。

さまざまなインポート方法をサポートしますが、インポートタスクの手動メンテナンスが必要です

データキャッシュの粒度

  • ブロックレベルのデータキャッシュをサポート
  • LRU キャッシュのエビクションメカニズムに従う
  • 計算結果はキャッシュされません

事前計算されたクエリの結果を保存

テーブルスキーマに基づいてデータを保存

クエリパフォーマンス

データキャッシュ ≤ マテリアライズドビュー = ネイティブテーブル

クエリステートメント

  • データレイクに対するクエリステートメントの変更は必要ありません
  • クエリがキャッシュにヒットした場合、計算が発生します。
  • データレイクに対するクエリステートメントの変更は必要ありません
  • クエリ書き換えを活用して事前計算結果を再利用します

ネイティブテーブルをクエリするためには、クエリステートメントの変更が必要です

データレイクから直接クエリを実行したり、データをネイティブテーブルにロードする場合と比較して、マテリアライズドビューはいくつかの独自の利点を提供します:

  • ローカルストレージでの高速化: マテリアライズドビューは、インデックス、パーティショニング、バケツ分割、およびコロケートグループなど、StarRocks のローカルストレージによる高速化の利点を活用することができます。これにより、データレイクから直接データをクエリする場合と比較して、より良いクエリパフォーマンスが得られます。
  • ローディングタスクのゼロメンテナンス: マテリアライズドビューは、自動リフレッシュタスクを通じてデータを透過的に更新します。スケジュールされたデータの更新を行うためにローディングタスクをメンテナンスする必要はありません。さらに、Hive カタログベースのマテリアライズドビューはデータの変更を検出し、パーティションレベルでの増分リフレッシュを実行することができます。
  • インテリジェントなクエリ書き換え: クエリはマテリアライズドビューを透過的に書き換えることができます。アプリケーションが使用するクエリステートメントを変更する必要なく、すぐに高速化の恩恵を受けることができます。

そのため、次のようなシナリオでマテリアライズドビューの使用をお勧めします:

  • データキャッシュが有効になっていても、クエリパフォーマンスがクエリレイテンシや同時性の要件を満たさない場合。
  • クエリに再利用可能なコンポーネント(固定の集計関数や結合パターンなど)が含まれている場合。
  • データがパーティションに構成されており、クエリに比較的高い水準での集計が関与している場合(日ごとに集計するなど)。

以下のシナリオでは、データキャッシュを介した高速化を優先することをお勧めします:

  • クエリには再利用可能なコンポーネントは多く含まれず、データレイクから任意のデータをスキャンする可能性がある場合。
  • リモートストレージには大きな変動や不安定性があり、アクセスに影響を及ぼす可能性がある場合。

外部カタログベースのマテリアライズドビューの作成

外部カタログのテーブルにマテリアライズドビューを作成する方法は、StarRocks のネイティブテーブルにマテリアライズドビューを作成する方法と似ています。適切なリフレッシュ戦略を設定し、外部カタログベースのマテリアライズドビューに対してクエリ書き換えを手動で有効にする必要があります。

適切なリフレッシュ戦略を選択する

現在、StarRocks は Hudi カタログ、Iceberg カタログ、JDBC カタログのパーティションレベルのデータ変更を検出することはできません。そのため、タスクがトリガされるたびにフルサイズのリフレッシュが実行されます。

Hive カタログの場合、Hive メタデータキャッシュリフレッシュ機能を有効にすることで、StarRocks はパーティションレベルでのデータ変更を検出できるようになります。ただし、マテリアライズドビューのパーティショニングキーは基になるテーブルのパーティショニングキーに含まれている必要があります。この機能を有効にすると、StarRocks は定期的に Hive メタストアサービス(Hive Metastore または AWS Glue)にアクセスして最近クエリされたホットデータのメタデータ情報を取得します。これにより、リフレッシュによるリソース消費を減らすために、データ変更のあるパーティションのみをリフレッシュすることができます。

Hive メタデータキャッシュリフレッシュ機能を有効にするには、次の FE ダイナミック設定項目を使用して、ADMIN SET FRONTEND CONFIG を実行します:

設定項目

デフォルト値

説明

enable_background_refresh_connector_metadata

v3.0 で true、v2.5 で false

定期的な Hive メタデータキャッシュのリフレッシュを有効にするかどうか。有効にすると、StarRocks は Hive クラスタのメタストア(Hive Metastore または AWS Glue)をポーリングし、よくアクセスされる Hive カタログのキャッシュされたメタデータをリフレッシュしてデータの変更を認識します。true は Hive メタデータキャッシュのリフレッシュを有効にし、false は無効にします。

background_refresh_metadata_interval_millis

600000(10 分)

2 回の連続する Hive メタデータキャッシュリフレッシュ間の間隔。単位: ミリ秒

background_refresh_metadata_time_secs_since_last_access_secs

86400(24 時間)

Hive カタログへのアクセス後、指定された時間以上アクセスされていない場合、StarRocks はキャッシュされたメタデータのリフレッシュを停止します。アクセスされていない Hive カタログの場合、StarRocks はキャッシュされたメタデータをリフレッシュしません。単位: 秒

外部カタログベースのマテリアライズドビューに対してクエリ書き換えを有効にする

デフォルトでは、StarRocks は Hudi、Iceberg、JDBC カタログ上のマテリアライズドビューに対するクエリ書き換えをサポートしていません。クエリ書き換えは、このシナリオでは結果の強力な一貫性を保証することができないためです。マテリアライズドビューにコンストラクトする際に非常に複雑なクエリステートメントを使用する場合は、クエリステートメントを分割し、ネストされた形式で複数の単純なマテリアライズドビューを構築することをお勧めします。ネストされたマテリアライズドビューはより多様性があり、さまざまなクエリパターンに対応することができます。

CREATE MATERIALIZED VIEW ex_mv_par_tbl
PARTITION BY emp_date
DISTRIBUTED BY hash(empid)
PROPERTIES (
"force_external_table_query_rewrite" = "true"
)
AS
select empid, deptno, emp_date
from `hive_catalog`.`emp_db`.`emps_par_tbl`
where empid < 5;

クエリ書き換えを伴うシナリオでは、非常に複雑なクエリステートメントを使用してマテリアライズドビューを構築する場合、クエリステートメントを分割し、複数の単純なマテリアライズドビューをネスト形式で構成することをお勧めします。ネストされたマテリアライズドビューはより柔軟で、さまざまなクエリパターンに対応することができます。

ベストプラクティス

実際のビジネスシナリオでは、監査ログやビッグクエリログの分析によって、実行レイテンシの高いクエリやリソース消費の多いクエリを特定することができます。さらに、クエリプロファイルを使用して、クエリが遅い具体的なステージを特定することもできます。次のセクションでは、マテリアライズドビューを使用してデータレイクのクエリパフォーマンスを向上させる方法についての手順と例を提供します。

ケース1: データレイク内の結合計算の高速化

マテリアライズドビューを使用して、データレイク内の結合クエリの高速化を実現できます。

以下の Hive カタログのクエリが特に遅いとします:

--Q1
SELECT SUM(lo_extendedprice * lo_discount) AS REVENUE
FROM hive.ssb_1g_csv.lineorder, hive.ssb_1g_csv.dates
WHERE
lo_orderdate = d_datekey
AND d_year = 1993
AND lo_discount BETWEEN 1 AND 3
AND lo_quantity < 25;

--Q2
SELECT SUM(lo_extendedprice * lo_discount) AS REVENUE
FROM hive.ssb_1g_csv.lineorder, hive.ssb_1g_csv.dates
WHERE
lo_orderdate = d_datekey
AND d_yearmonth = 'Jan1994'
AND lo_discount BETWEEN 4 AND 6
AND lo_quantity BETWEEN 26 AND 35;

--Q3
SELECT SUM(lo_revenue), d_year, p_brand
FROM hive.ssb_1g_csv.lineorder, hive.ssb_1g_csv.dates, hive.ssb_1g_csv.part, hive.ssb_1g_csv.supplier
WHERE
lo_orderdate = d_datekey
AND lo_partkey = p_partkey
AND lo_suppkey = s_suppkey
AND p_brand BETWEEN 'MFGR#2221' AND 'MFGR#2228'
AND s_region = 'ASIA'
GROUP BY d_year, p_brand
ORDER BY d_year, p_brand;

クエリプロファイルを分析することで、lineorder テーブルとその他のディメンションテーブルの間のハッシュ結合にかかる時間が大部分を占めていることがわかることがあります。

ここでは、Q1 と Q2 は lineorderdates を結合してから集計を実行し、Q3 は lineorderdatespart、および supplier を結合した後に集計を実行します。

そのため、lineorderdatespartsupplier を結合するマテリアライズドビューを構築するため、StarRocks の View Delta Join rewrite 機能を利用することができます。

CREATE MATERIALIZED VIEW lineorder_flat_mv
DISTRIBUTED BY HASH(LO_ORDERDATE, LO_ORDERKEY) BUCKETS 48
PARTITION BY LO_ORDERDATE
REFRESH ASYNC EVERY(INTERVAL 1 DAY)
PROPERTIES (
-- ユニーク制約を指定します。
"unique_constraints" = "
hive.ssb_1g_csv.supplier.s_suppkey;
hive.ssb_1g_csv.part.p_partkey;
hive.ssb_1g_csv.dates.d_datekey",
-- 外部カタログベースのマテリアライズドビューに対してクエリ書き換えを有効にします。
"force_external_table_query_rewrite" = "TRUE"
)
AS SELECT
l.LO_ORDERDATE AS LO_ORDERDATE,
l.LO_ORDERKEY AS LO_ORDERKEY,
l.LO_PARTKEY AS LO_PARTKEY,
l.LO_SUPPKEY AS LO_SUPPKEY,
l.LO_QUANTITY AS LO_QUANTITY,
l.LO_EXTENDEDPRICE AS LO_EXTENDEDPRICE,
l.LO_DISCOUNT AS LO_DISCOUNT,
l.LO_REVENUE AS LO_REVENUE,
s.S_REGION AS S_REGION,
p.P_BRAND AS P_BRAND,
d.D_YEAR AS D_YEAR,
d.D_YEARMONTH AS D_YEARMONTH
FROM hive.ssb_1g_csv.lineorder AS l
INNER JOIN hive.ssb_1g_csv.supplier AS s ON s.S_SUPPKEY = l.LO_SUPPKEY
INNER JOIN hive.ssb_1g_csv.part AS p ON p.P_PARTKEY = l.LO_PARTKEY
INNER JOIN hive.ssb_1g_csv.dates AS d ON l.LO_ORDERDATE = d.D_DATEKEY;

ケース2: データレイクの集計および結合の高速化

集計クエリは、テーブル単体での集計クエリため、複数テーブルを組み合わせた集計クエリのいずれでも、マテリアライズドビューを使用して高速化することができます。

  • テーブル単位の集計クエリ通常のテーブルに対するクエリでは、そのクエリプロファイルで AGGREGATE ノードが多くの時間を消費していることがわかります。一般的な集計演算子を使用してマテリアライズドビューを構築することができます。次のクエリが遅い場合を考えます:
    --Q4
    SELECT
    lo_orderdate, count(distinct lo_orderkey)
    FROM hive.ssb_1g_csv.lineorder
    GROUP BY lo_orderdate
    ORDER BY lo_orderdate limit 100;
    Q4 は固有のオーダー数を日別に計算します。クエリは count distinct の計算を行うため、計算コストが高くなる可能性があります。これを加速するために、次の2つのタイプのマテリアライズドビューを作成できます:
    CREATE MATERIALIZED VIEW mv_2_1 
    DISTRIBUTED BY HASH(lo_orderdate)
    PARTITION BY LO_ORDERDATE
    REFRESH ASYNC EVERY(INTERVAL 1 DAY)
    AS
    SELECT
    lo_orderdate, count(distinct lo_orderkey)
    FROM hive.ssb_1g_csv.lineorder
    GROUP BY lo_orderdate;

    CREATE MATERIALIZED VIEW mv_2_2
    DISTRIBUTED BY HASH(lo_orderdate)
    PARTITION BY LO_ORDERDATE
    REFRESH ASYNC EVERY(INTERVAL 1 DAY)
    AS
    SELECT
    -- lo_orderkeyはBIGINT型である必要があるため、クエリ書き換えに使用することができます。
    lo_orderdate, bitmap_union(to_bitmap(lo_orderkey))
    FROM hive.ssb_1g_csv.lineorder
    GROUP BY lo_orderdate;
    注: この文脈において、LIMIT 句と ORDER BY 句がある場合は、書き換えエラーが発生しないように、マテリアライズドビューは作成しないでください。クエリ書き換えの制限事項については、クエリ書き換えによる制限事項を参照してください。
  • 複数テーブルの集計クエリ結合結果の集計を行うシナリオでは、テーブルを結合するマテリアライズドビューを作成し、結合結果をさらに集計するための既存のマテリアライズドビューまたはビューをネスト形式で作成することができます。たとえば、ケース1の例に基づいて、以下のマテリアライズドビューを作成することで、Q1 および Q2 の加速を図ることができます。
    CREATE MATERIALIZED VIEW mv_2_3
    DISTRIBUTED BY HASH(lo_orderdate)
    PARTITION BY LO_ORDERDATE
    REFRESH ASYNC EVERY(INTERVAL 1 DAY)
    AS
    SELECT
    lo_orderdate, lo_discount, lo_quantity, d_year, d_yearmonth, SUM(lo_extendedprice * lo_discount) AS REVENUE
    FROM lineorder_flat_mv
    GROUP BY lo_orderdate, lo_discount, lo_quantity, d_year, d_yearmonth;
    もちろん、結合と集計の計算を単一のマテリアライズドビュー内で実行することも可能です。これらのタイプのマテリアライズドビューはクエリ書き換えの機会が少なくなる可能性がありますが(特定の演算を行うための演算子があります)、集計後の保存領域は通常よりも少なくなります。具体的なユースケースに基づいて選択することができます。
    CREATE MATERIALIZED VIEW mv_2_4
    DISTRIBUTED BY HASH(lo_orderdate)
    PARTITION BY LO_ORDERDATE
    REFRESH ASYNC EVERY(INTERVAL 1 DAY)
    PROPERTIES (
    "force_external_table_query_rewrite" = "TRUE"
    )
    AS
    SELECT lo_orderdate, lo_discount, lo_quantity, d_year, d_yearmonth, SUM(lo_extendedprice * lo_discount) AS REVENUE
    FROM hive.ssb_1g_csv.lineorder, hive.ssb_1g_csv.dates
    WHERE lo_orderdate = d_datekey
    GROUP BY lo_orderdate, lo_discount, lo_quantity, d_year, d_yearmonth;

ケース3: 集計の結果を結合のクエリの高速化する

いくつかのシナリオでは、まずテーブルでの集計計算を実行し、その後他のテーブルとの結合クエリを実行する必要がある場合があります。StarRocks のクエリ書き換え機能を最大限に活用するために、ネストされたマテリアライズドビューを構築することをお勧めします。例えば:

--Q5
SELECT * FROM (
SELECT
l.lo_orderkey, l.lo_orderdate, c.c_custkey, c_region, sum(l.lo_revenue)
FROM
hive.ssb_1g_csv.lineorder l
INNER JOIN (
SELECT distinct c_custkey, c_region
from
hive.ssb_1g_csv.customer
WHERE
c_region IN ('ASIA', 'AMERICA')
) c ON l.lo_custkey = c.c_custkey
GROUP BY l.lo_orderkey, l.lo_orderdate, c.c_custkey, c_region
) c1
WHERE
lo_orderdate = '19970503';

Q5 はまず customer テーブルに対して集計クエリを実行し、次に lineorder テーブルとの結合および集計を実行します。同様のクエリでは、c_region および lo_orderdate に対して異なるフィルタが含まれる場合があります。クエリ書き換えの恩恵を受けるために、集計と結合用の2つのマテリアライズドビューを作成できます。

--mv_3_1
CREATE MATERIALIZED VIEW mv_3_1
DISTRIBUTED BY HASH(c_custkey)
REFRESH ASYNC EVERY(INTERVAL 1 DAY)
PROPERTIES (
"force_external_table_query_rewrite" = "TRUE"
)
AS
SELECT distinct c_custkey, c_region from hive.ssb_1g_csv.customer;

--mv_3_2
CREATE MATERIALIZED VIEW mv_3_2
DISTRIBUTED BY HASH(lo_orderdate)
PARTITION BY LO_ORDERDATE
REFRESH ASYNC EVERY(INTERVAL 1 DAY)
PROPERTIES (
"force_external_table_query_rewrite" = "TRUE"
)
AS
SELECT l.lo_orderdate, l.lo_orderkey, mv.c_custkey, mv.c_region, sum(l.lo_revenue)
FROM hive.ssb_1g_csv.lineorder l
INNER JOIN mv_3_1 mv
ON l.lo_custkey = mv.c_custkey
GROUP BY l.lo_orderkey, l.lo_orderdate, mv.c_custkey, mv.c_region;

ケース4: データレイクのリアルタイムデータと過去のデータを分離して処理する

次のシナリオを考えてみましょう。過去3日以内に更新されたデータは StarRocks に直接書き込まれ、それ以前のデータはチェックされ、バッチで Hive に書き込まれます。しかし、過去7日間のデータを含むクエリもあります。この場合、マテリアライズドビューを使用して自動的にデータを破棄する単純なメカニズムを構築することができます。

CREATE MATERIALIZED VIEW mv_4_1 
DISTRIBUTED BY HASH(lo_orderdate)
PARTITION BY LO_ORDERDATE
REFRESH ASYNC EVERY(INTERVAL 1 DAY)
AS
SELECT lo_orderkey, lo_orderdate, lo_revenue
FROM hive.ssb_1g_csv.lineorder
WHERE lo_orderdate<=current_date()
AND lo_orderdate>=date_add(current_date(), INTERVAL -4 DAY);

この上位アプリケーションのロジックに基づいてビューやマテリアライズドビューを構築することができます。