【Road to Cassandra Day】Cassandraのマテリアライズド・ビュー

# はじめに

## Cassandra Day Tokyo

今年、2023年６月１日に、[Cassandra Day](https://www.datastax.com/events/cassandra-day-japan)が日本でも開催されます。
Cassandra Dayは、昨年、ベルリン、ロンドン、アムステルダム、ハノイ、ジャカルタ、ヒューストン、サンタクララ、シアトル、シンガポールでも開催されました。

今回の東京での開催に向けて、Apache Cassandraに関する記事を発表していきます。

[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176567/6a879803-d135-348b-f815-08be011607fa.png)](https://www.datastax.com/events/cassandra-day-japan)

## Apache Cassandraについて

Apache Cassandraとは、一言でいうなら、オープンソースの分散データベース管理システムです。

他の分散データベース管理システム同様、複数の汎用サーバーを用いて、ひとつのデータベースを構築します（開発などの目的のため、一つのサーバーのみで構成することも可能です）。

ここでは、詳しい説明は割愛し、興味のある方へのご紹介の役割は、公式サイトやWikipediaに譲ります。

https://cassandra.apache.org/_/index.html

https://en.wikipedia.org/wiki/Apache_Cassandra


## Cassandraのマテリアライズド・ビュー

Cassandraのマテリアライズド・ビューについて説明します。


Cassandra（やHBaseのようなワイドカラムと呼ばれるデータベース）では、「クエリドリブンアプローチ」呼ばれるように、クエリの要件に沿って、テーブルを設計・定義します。そして、格納されるデータが同じであっても、異なる検索のニーズがある場合は、そのクエリに対応する別のテーブルを定義します。

この「異なる検索のニーズ」のために、Cassandraの提供するマテリアライズド・ビューの機能を活用することも考えられます。

### Cassandraのマテリアライズド・ビュー

Cassandraでは、既存のテーブル（ソース・テーブル）のデータを使用し、新しいプライマリ・キーと新しいプロパティを指定して、マテリアライズド・ビューを作成することができます。マテリアライズド・ビューのデータは、ソース・テーブルを変更すると自動的に更新されます。ソーステーブルからデータが削除されると、関連するマテリアライズド・ビューから同じデータが削除されます。

なお、クライアントがマテリアライズド・ビューに、データを直接書き込むことはできません。

データをソース・テーブルに挿入した後、マテリアライズド・ビューが非同期で更新されるため、マテリアライズド・ビューの更新には、ソーステーブルの更新に対して、遅延が生じます。

## マテリアライズド・ビューに定義に関する制限事項

 - マテリアライズド・ビューのプライマリ・キーにソース・テーブルのプライマリ・キーをすべて含めます。
 - マテリアライズド・ビューのプライマリ・キーに追加できるカラムは1つのみです。スタティックカラムは使用できません。
 - マテリアライズド・ビューのプライマリ・キーとして指定されたカラムにNull値を持つ行を除外します。

マテリアライズド・ビューは、独自のWHERE条件とプロパティを使用して作成できます。

### （セカンダリ）インデックスと使い分けの指針

既存のテーブルを活用して、「異なる検索のニーズ」を満たす方法として、セカンダリ・インデックスも存在します。
これらの使い分けには、以下の指針があります。

 - **マテリアライズド・ビュー**は、**カーディナリティが高いデータ**に適しています。マテリアライズド・ビューのデータは、ビューのプライマリ・キーに基づいて連続して配置されます。カーディナリティが低いデータを挿入すると、マテリアライズド・ビューではホットスポット(特定のデータ、つまりノードへのアクセス集中)が生じます。


 - **セカンダリ・インデックス**は、**カーディナリティが低いデータ**に適しています。セカンダリ・インデックスに対してカーディナリティが高いカラムのクエリーを実行するには、データベースがクラスター内のすべてのノードにアクセスする必要があるため、読み取りレイテンシーが高くなります。


## マテリアライズド・ビューの例

まず、以下のような既存のテーブルがあるとします。

```sql
CREATE TABLE cyclist (cid UUID PRIMARY KEY, name text, age int, birthday date, country text);
```

このテーブルをソース・テーブルとして以下のようにマテリアライズド・ビューを作成することができます。

```sql
CREATE MATERIALIZED VIEW cyclist_by_age 
AS SELECT age, birthday, name, country 
FROM cyclist 
WHERE age IS NOT NULL AND cid IS NOT NULL 
PRIMARY KEY (age, cid);
```

この`CREATE MATERIALIZED VIEW`文には複数の機能があります。
　- `AS SELECT`句はベース・テーブルからマテリアライズド・ビューにコピーするカラムを指定します。
 - `FROM`句は、データのコピー元であるソース・テーブルを指定します。
 - `WHERE`句は、すべてのプライマリ・キー・カラムのデータのある行のみがマテリアライズド・ビューにコピーされるように、`IS NOT NULL`句を使用してすべてのプライマリ・キー・カラムを含める必要があります。
他のテーブルと同様に、プライマリ・キー・カラムを指定します。`cyclist`（ソース・テーブル）ではプライマリ・キーとして`cid`を使用しているため、マテリアライズド・ビューのプライマリ・キーに`cid`が含まれている必要があります。

注: このマテリアライズド・ビューでは、プライマリ・キーとして`age`を使用しています。、`cid`はクラスタリングカラムです。DataStax Enterprise 5.0以前では、クラスター化カラムの最大サイズは64 KBです。

このマテリアライズド・ビューは、サイクリストの年齢に基づいたクエリーに対応します。

```sql
SELECT age, name, birthday FROM cyclist_by_age WHERE age = 18;
```

同じソース・テーブルに基づく別のマテリアライズド・ビューで、サイクリストの生年月日や出身国ごとに情報を整理することができます。

```sql
CREATE MATERIALIZED VIEW cyclist_by_birthday 
AS SELECT age, birthday, name, country 
FROM cyclist
WHERE birthday IS NOT NULL AND cid IS NOT NULL
PRIMARY KEY (birthday, cid);

CREATE MATERIALIZED VIEW cyclist_by_country 
AS SELECT age,birthday, name, country 
FROM cyclist 
WHERE country IS NOT NULL AND cid IS NOT NULL
PRIMARY KEY (country, cid);
```

以下のクエリーでは、新しいマテリアライズド・ビューを使用します。

```sql
SELECT age, name, birthday FROM cyclist_by_country WHERE country = 'Netherlands';

SELECT age, name, birthday FROM cyclist_by_birthday WHERE birthday = '1987-09-04';
```

非プライマリ・キー・カラムに関する制限を含むフィルター処理を使用してマテリアライズド・ビューを作成することもできます。

```sql
CREATE MATERIALIZED VIEW cyclist_by_birthday_Netherlands 
AS SELECT age, birthday, name, country 
FROM cyclist 
WHERE birthday IS NOT NULL AND cid IS NOT NULL
AND country='Netherlands'
PRIMARY KEY (birthday, cid);
```

このマテリアライズド・ビューは、`AND country='Netherlands'`を`WHER`E句に追加することで、出身国がオランダ（Netherlands）のサイクリストの情報のみを格納します。また、特定の生年月日のオランダのサイクリストを検索するクエリーを行うことができます。

```sql
SELECT age, name, birthday FROM cyclist_by_birthday WHERE birthday = '1997-02-08';
```




## 参考情報

マテリアライズド・ビューの仕組みの詳細については、下記ドキュメント等を参照することができます。



https://docs.datastax.com/ja/dse/5.1/cql/cql/cql_using/useCreateMV.html

https://www.datastax.com/blog/new-cassandra-30-materialized-views

https://www.slideshare.net/carlyeks/cassandra-materialized-views