👌

Snowflake マテリアライズドビューについて

2022/11/15に公開1

今回はマテリアライズドビューについて動作確認していきます。

マテリアライズドビューとは?

ドキュメントより抜粋
マテリアライズドビューは、クエリ仕様(ビュー定義の SELECT )から
派生した事前に計算されたデータセットであり、後で使用するために保存されます。
データは事前に計算されているため、マテリアライズドビューのクエリは、
ビューのベーステーブルに対してクエリを実行するよりも高速です。
このパフォーマンスの違いは、クエリが頻繁に実行される場合、
または非常に複雑な場合に顕著になります。
その結果、マテリアライズドビューは、特に頻繁に実行され、
大規模なデータセットで実行される、高価な集計、射影、および選択操作を高速化できます。

環境の準備

キャッシュをOFFにしておきます

マテリアライズドビューを使うと使わないとでどれくらい速度の違いが出るか確認するための処置です。

ALTER SESSION SET USE_CACHED_RESULT=FALSE;
ALTER warehouse snowflake_wh suspend;
ALTER warehouse snowflake_wh resume;

データベースの作成

CREATE OR REPLACE TRANSIENT DATABASE ORDERS;

snowflakeにデフォルトで用意されている大規模データ(TPCH_SF100.ORDERS)をORDERSにコピーします。

CREATE OR REPLACE SCHEMA TPCH_SF100;
CREATE OR REPLACE TABLE TPCH_SF100.ORDERS AS
SELECT * FROM SNOWFLAKE_SAMPLE_DATA.TPCH_SF100.ORDERS;

TPCH_SF100.ORDERSは1億5000万行あり、データサイズは4.3GBあります。

クエリを実行してみます。

クエリに意味はないと思います。

SELECT
YEAR(O_ORDERDATE) AS YEAR,
MAX(O_COMMENT) AS MAX_COMMENT,
MIN(O_COMMENT) AS MIN_COMMENT,
MAX(O_CLERK) AS MAX_CLERK,
MIN(O_CLERK) AS MIN_CLERK
FROM ORDERS.TPCH_SF100.ORDERS
GROUP BY YEAR(O_ORDERDATE)
ORDER BY YEAR(O_ORDERDATE);

クエリ実行時間は7.25秒でした。

ユースケース

先のクエリを頻繁に実行したいユーザが多数といると仮定します。
そうするとコスト問題や、ユーザエクスペリエンスなど懸念が出てきます。
そこでマテリアライズドビューを使います。

マテリアライズドビューの作成

CREATE OR REPLACE MATERIALIZED VIEW ORDERS_MV
AS 
SELECT
YEAR(O_ORDERDATE) AS YEAR,
MAX(O_COMMENT) AS MAX_COMMENT,
MIN(O_COMMENT) AS MIN_COMMENT,
MAX(O_CLERK) AS MAX_CLERK,
MIN(O_CLERK) AS MIN_CLERK
FROM ORDERS.TPCH_SF100.ORDERS
GROUP BY YEAR(O_ORDERDATE);

クエリ実行時間は12.46秒でした。
ビューが作成されていることを確認できました。

SQLでも確認できます。

SHOW MATERIALIZED VIEWS;

マテリアライズドビューの実行

SELECT * FROM ORDERS_MV;

なんと驚きの1.35秒で返ってきました。さきほどの7.25秒と比較すると格段に速くなっています。

さらにYEARカラムの昇順でクエリを実行してみます。

SELECT * FROM ORDERS_MV ORDER BY YEAR;

1.29秒と速いですね。

データに変更が加えられるとどうなるか?

データを更新したらどうなるか見てみましょう。

UPDATEで値を更新する

UPDATE ORDERS
SET O_CLERK='Clerk#99900000' 
WHERE O_ORDERDATE='1992-01-01'

値が更新されていることを確認する

SELECT
YEAR(O_ORDERDATE) AS YEAR,
MAX(O_COMMENT) AS MAX_COMMENT,
MIN(O_COMMENT) AS MIN_COMMENT,
MAX(O_CLERK) AS MAX_CLERK,
MIN(O_CLERK) AS MIN_CLERK
FROM ORDERS.TPCH_SF100.ORDERS
GROUP BY YEAR(O_ORDERDATE);

再度マテリアライズドビューを実行してみる

SELECT * FROM ORDERS_MV;

クエリ実行速度は153msと速い結果となりました。
結果から判断するにテーブルを更新しても、その結果がマテリアライズドビューにも反映されていると思っていいのかな?

Discussion

mmotohasmmotohas

いつもありがとうございます!MViewは常に最新のデータを返します。
https://docs.snowflake.com/ja/user-guide/views-materialized.html#advantages-of-materialized-views

ベーステーブルで実行された DML の量に関係なく、マテリアライズドビューを介してアクセスされるデータは常に最新です。マテリアライズドビューが最新になる前にクエリが実行されると、Snowflakeはマテリアライズドビューを更新するか、マテリアライズドビューの最新部分を使用して、必要な新しいデータをベーステーブルから取得します。