Cassandraのデータモデリング

Cassandraでのデータモデリング

1. 概要

Cassandraは、パフォーマンスを犠牲にすることなく高可用性と水平スケーラビリティを提供するNoSQLデータベースです。

Cassandraから最高のパフォーマンスを引き出すには、手元のビジネス問題に固有のクエリパターンに関するスキーマを慎重に設計する必要があります。

この記事では、how to approach data modeling in Cassandraに関するいくつかの重要な概念を確認します。

先に進む前に、Cassandra with Javaの記事を読んで、Javaを使用してCassandraに接続する方法と基本を理解することができます。

2. パーティションキー

Cassandraは、データがクラスター内の複数のノードに分割されて保存される分散データベースです。

パーティションキーは1つ以上のデータフィールドで構成され、used by the partitioner to generate a token via hashing to distribute the data uniformly across a clusterです。

3. クラスタリングキー

クラスタリングキーは1つ以上のフィールドで構成され、同じパーティションキーを持つ行をクラスター化またはグループ化し、ソートされた順序で保存するのに役立ちます。

時系列データをCassandraに保存していて、データを時系列で取得したいとします。 時系列データフィールドを含むクラスタリングキーは、このユースケースのデータを効率的に取得するのに非常に役立ちます。

注:パーティションキーとクラスタリングキーの組み合わせが主キーを構成し、Cassandraクラスター内のすべてのレコードを一意に識別します。

4. クエリパターンに関するガイドライン

Cassandraでデータモデリングを開始する前に、クエリパターンを特定し、次のガイドラインを順守する必要があります。

  1. 各クエリは、単一のパーティションからデータを取得する必要があります

  2. Cassandraには、単一のパーティションに格納できる列の数に制限があるため、パーティションに格納されるデータの量を追跡する必要があります

  3. 同じデータで異なる種類のクエリパターンをサポートするために、データを非正規化して複製してもかまいません

上記のガイドラインに基づいて、実際のユースケースと、それらのCassandraデータモデルをモデル化する方法を見てみましょう。

5. 実世界のデータモデリングの例

5.1. Facebookの投稿

さまざまなユーザーのFacebook投稿をCassandraに保存するとします。 一般的なクエリパターンの1つは、特定のユーザーによって作成された上位の ‘N‘投稿をフェッチすることです。

したがって、上記のガイドラインに従って、we need tostore all data for a particular user on a single partition

また、投稿のタイムスタンプをクラスタリングキーとして使用すると、上位の「N」の投稿をより効率的に取得するのに役立ちます。

このユースケースのCassandraテーブルスキーマを定義しましょう。

CREATE TABLE posts_facebook (
  user_id uuid,
  post_id timeuuid,
  content text,
  PRIMARY KEY (user_id, post_id) )
WITH CLUSTERING ORDER BY (post_id DESC);

それでは、ユーザーAnnaの上位20件の投稿を検索するクエリを作成しましょう。

SELECT content FROM posts_facebook WHERE user_id = "Anna_id" LIMIT 20

5.2. 全国のジム

多くの国のさまざまな都市と州にまたがるさまざまなパートナージムの詳細を保存しており、特定の都市のジムを取得したいとします。

また、ジムを開業日で並べ替えた結果を返す必要があるとします。

上記のガイドラインに基づいて、特定の州および国の特定の都市にあるジムを1つのパーティションに格納し、開始日とジム名をクラスタリングキーとして使用する必要があります。

この例のCassandraテーブルスキーマを定義しましょう。

CREATE TABLE gyms_by_city (
 country_code text,
 state text,
 city text,
 gym_name text,
 opening_date timestamp,
 PRIMARY KEY (
   (country_code, state_province, city),
   (opening_date, gym_name))
 WITH CLUSTERING ORDER BY (opening_date ASC, gym_name ASC);

それでは、米国内のフェニックス市の開業日までに最初の10のジムを取得するクエリを見てみましょう。 アリゾナ州:

SELECT * FROM gyms_by_city
  WHERE country_code = "us" AND state = "Arizona" AND city = "Phoenix"
  LIMIT 10

次に、米国内のフェニックス市で最近オープンした10のジムを取得するクエリを見てみましょう。 アリゾナ州:

SELECT * FROM gyms_by_city
  WHERE country_code = "us" and state = "Arizona" and city = "Phoenix"
  ORDER BY opening_date DESC
  LIMIT 10

注:最後のクエリの並べ替え順序は、テーブルの作成時に定義された並べ替え順序とは逆であるため、Cassandraが最初にデータをフェッチしてからメモリに並べ替えるため、クエリの実行速度が遅くなります。

5.3. Eコマースの顧客と製品

eコマースストアを運営していて、CustomerProductの情報をCassandra内に保存しているとしましょう。 このユースケースに関連する一般的なクエリパターンのいくつかを見てみましょう。

  1. Customerの情報を取得する

  2. Productの情報を取得する

  3. 特定のProductが好きなすべてのCustomersを取得します

  4. 指定されたCustomerのいいねをすべてのProductsを取得します

CustomerProductの情報を格納するために別々のテーブルを使用することから始めます。 ただし、上記の3番目と4番目のクエリをサポートするには、かなりの量の非正規化を導入する必要があります。

これを実現するために、さらに2つのテーブル「Customer_by_Product」と「Product_by_Customer」を作成します。

この例のCassandraテーブルスキーマを見てみましょう。

CREATE TABLE Customer (
  cust_id text,
  first_name text,
  last_name text,
  registered_on timestamp,
  PRIMARY KEY (cust_id));

CREATE TABLE Product (
  prdt_id text,
  title text,
  PRIMARY KEY (prdt_id));

CREATE TABLE Customer_By_Liked_Product (
  liked_prdt_id text,
  liked_on timestamp,
  title text,
  cust_id text,
  first_name text,
  last_name text,
  PRIMARY KEY (prdt_id, liked_on));

CREATE TABLE Product_Liked_By_Customer (
  cust_id text,
  first_name text,
  last_name text,
  liked_prdt_id text,
  liked_on timestamp,
  title text,
  PRIMARY KEY (cust_id, liked_on));

注:クエリ、特定の顧客による最近高く評価された製品、および特定の製品を最近高く評価した顧客の両方をサポートするために、クラスタリングキーとして「liked_on」列を使用しました。

クエリを見て、製品「Pepsi」を最近気に入った10人の顧客を見つけましょう。

SELECT * FROM Customer_By_Liked_Product WHERE title = "Pepsi" LIMIT 10

そして、「Anna」という名前の顧客が最近気に入った製品(最大10個)を見つけるクエリを見てみましょう。

SELECT * FROM Product_Liked_By_Customer
  WHERE first_name = "Anna" LIMIT 10

6. 非効率的なクエリパターン

Cassandraがデータを保存する方法のため、次のような一部のクエリパターンはまったく効率的ではありません。

  • Fetching data from multiple partitions –これには、コーディネーターが複数のノードからデータをフェッチし、それを一時的にヒープに格納してから、結果をユーザーに返す前にデータを集約する必要があります。

  • Join-based queries –分散型であるため、Cassandraはリレーショナルデータベースと同じようにクエリでのテーブル結合をサポートしていません。その結果、queries withjoins will be slower and can also lead to inconsistency and availability issues

7. 結論

このチュートリアルでは、Cassandraでデータモデリングにアプローチする方法に関するいくつかのベストプラクティスを取り上げました。

コアの概念を理解し、クエリパターンを事前に識別することは、Cassandraクラスターから最高のパフォーマンスを得る正しいデータモデルを設計するために必要です。