Amazon Web Services ブログ

クエリの実行を速めるために Amazon Redshift のビューをマテリアライズする

AWS では、ネットワーク、コンピューティングリソース、またはオブジェクトストレージなどのクラウドサービスの管理とアクセスを簡略化するために、最新の仮想テクノロジーの構築を得意としています。

あるリレーショナルデータベース管理システム (RDBMS) では、1 つのビューはテーブルに適用された仮想化であり、データベースクエリの結果を表す仮想テーブルと言えます。ビューはスキーマの設計時によく使用されます。データのサブセット、要約されたデータ (集約または変換されたデータ) の表示、または複数のテーブル間でのデータアクセスの簡略化などがその用途です。Amazon Redshift などのデータウェアハウスを使用すると、1 つのビューで、Amazon QuickSight または Tableau などのビジネスインテリジェンス (BI) ツールの複数のテーブルからの集約データへ簡易的にアクセスできるようになります。

ビューによって使いやすさや順応性は高まりますが、データアクセスのスピードは落ちます。データベースシステムはアプリケーションがビューにアクセスするたびに、ビューを示す基盤となるクエリを評価しなければならなくなります。パフォーマンスが重要な場合、データエンジニアはその代替手段として、create table as (CTAS) を使用します。CTAS はクエリで定義されたテーブルです。このクエリはテーブルの作成時に実行され、アプリケーションは通常のテーブルとしてそれを使用できます。これの不便なところは基盤となるデータが更新されたときに、CTAS のデータセットは更新されないことです。さらに、 CTAS の定義はデータベースシステム内に保存されません。そのため、テーブルが CTAS によって作成されたかを知ることは不可能で、どの CTAS を更新する必要があるか、どれが最新かを追跡するのは困難になります。

今日は、Amazon Redshiftマテリアライズドビューをご紹介します。マテリアライズドビュー (MV) はクエリのデータを含むデータベースオブジェクトです。マテリアライズドビューはビューのキャッシュのようなものと考えられます。実行時にデータセットを構築、計算する代わりに、マテリアライズドビューはビューを作成した時点で計算を事前に実行し、データアクセスを保存および最適化します。データは通常のテーブルデータと同様に、クエリに使用できます。

分析クエリでマテリアライズドビューを使用すると、クエリの実行時間を桁違いに短縮できます。その理由はマテリアライズドビューを定義するクエリが、すでに実行済みで、データがデータベースシステムで利用できる状態になっているためです。

マテリアライズドビューは予測可能で何度も繰り返し実行できるクエリで特に便利です。大きなテーブルにリソースをたくさん使うクエリを実行する代わりに、アプリケーションはマテリアライズドビューに保存された計算済みのデータに対してクエリを実行できます。

ベーステーブルのデータが変動するときは、Redshift の SQL ステートメント “refresh materialized view“ を実行して、マテリアライズドビューを更新します。更新ステートメントの実行後、マテリアライズドビューには通常のビューで返されたのと同等のデータが含まれます。更新は増分のみ、または完全更新 (再計算) のいずれかになります。可能な場合、Redshift はマテリアライズドビューが最後に更新されてからベーステーブルで変更のあったデータのみを増分更新します。

それでは、その仕組み見てみましょう。販売情報を格納するためにサンプルスキーマを作成します。販売情報は販売トランザクションと商品が販売された店の詳細情報で構成されています。

都市別販売金額合計を表示するために、create materialized view SQL ステートメントを使用して、マテリアライズドビューを作成します。Redshift コンソールに接続し、クエリエディターを選択して、次のステートメントを入力し、マテリアライズドビューを作成し (city_sales) 2 つのテーブルのレコードを結合して都市 (group by city) ごとの販売金額 (sum(sales.amount)) を集約します。

CREATE MATERIALIZED VIEW city_sales AS (
  SELECT st.city, SUM(sa.amount) as total_sales
  FROM sales sa, store st
  WHERE sa.store_id = st.id
  GROUP BY st.city
);

結果スキーマは以下のようになります。

これで通常のビューやテーブルと同じように、マテリアライズドビューにクエリを実行し、“SELECT city, total_sales FROM city_sales” のようなステートメントを発行して、以下の結果を取得できます。この 2 つのテーブル間の結合と集約 (sumgroup by) はすでに計算されているので、スキャン対象となるデータは大幅に少なくなります。

基礎となるベーステーブルのデータが変化すると、マテリアライズドビューではこれらの変化が自動的に反映されません。マテリアライズドビューに格納されていたデータは、SQL の refreshmaterialized view コマンドを使用し、基礎となるベーステーブルから必要に応じて更新できます。実践的な例を見てみましょう。

!-- let's add a row in the sales base table
INSERT INTO sales (id, item, store_id, customer_id, amount)
VALUES(8, 'Gaming PC Super ProXXL', 1, 1, 3000);

SELECT city, total_sales FROM city_sales WHERE city = 'Paris'

city |total_sales|
-----|-----------|
Paris|        690|

!-- the new sale is not taken into account !

!-- let's refresh the materialized view
REFRESH MATERIALIZED VIEW city_sales;

SELECT city, total_sales FROM city_sales WHERE city = 'Paris'

city |total_sales|
-----|-----------|
Paris|       3690|

!-- now the view has the latest sales data

このごくシンプルなデモのコード全文は 参照用としてご覧いただけます

マテリアライズドビューは AWS の全リージョンで今日から使用できるようになります。

マテリアライズドビューの使用を開始するのに既存のクラスターに変更を加える必要はありません。一切の追加コストなしに今日から作成できます。

構築がうまくいきますように。