Cassandra ドキュメント

バージョン

プレリリース版のドキュメントを表示しています。

データモデルの評価と改善

物理モデルを作成したら、最適なパフォーマンスを確保するために、テーブル設計を評価および改善するためのいくつかの手順を実行する必要があります。

パーティションサイズの計算

最初に確認したいのは、テーブルに過度に大きなパーティション、言い換えれば、幅が広すぎるパーティションがあるかどうかです。パーティションのサイズは、パーティションに格納されているセル (値) の数で測定されます。Cassandra のハードリミットは 1 パーティションあたり 20 億セルですが、その制限に達する前にパフォーマンスの問題が発生する可能性があります。

パーティションのサイズを計算するには、次の式を使用します。

\[N_v = N_r (N_c - N_{pk} - N_s) + N_s\]

パーティション内の値 (またはセル) の数 (Nv) は、静的列の数 (Ns) に、行数 (Nr) と 1 行あたりの値の数を掛けたものに等しくなります。1 行あたりの値の数は、列数 (Nc) から主キー列数 (Npk) と静的列数 (Ns) を引いたものとして定義されます。

列数は比較的静的な傾向がありますが、実行時にテーブルを変更することは可能です。このため、パーティションサイズの主な要因は、パーティション内の行数です。これは、パーティションが大きくなりすぎる可能性を判断する際に考慮する必要がある重要な要素です。20 億の値は多く聞こえますが、センサーシステムでは、毎ミリ秒ごとに数十または数百の値が測定されるため、値の数は非常に速く増加し始めます。

パーティションサイズを分析するために、テーブルの 1 つを見てみましょう。ホテルごとに 1 つのパーティションを持つワイドパーティション設計であるため、available_rooms_by_hotel_date テーブルを見てみましょう。テーブルには、3 つの主キー列 (Npk = 3) と静的列 (Ns = 0) を含む合計 4 つの列 (Nc = 4) があります。これらの値を式に代入すると、次のようになります。

\[N_v = N_r (4 - 3 - 0) + 0 = 1N_r\]

したがって、このテーブルの値の数は、行数に等しくなります。行数を決定する必要があるため、アプリケーション設計に基づいて推定を行います。テーブルは、ホテルごとの各部屋の毎晩の記録を保存しています。システムは、一度に 2 年分の在庫を保存するために使用され、システムには平均 100 部屋がある 5,000 のホテルがあると仮定しましょう。

ホテルごとにパーティションがあるため、パーティションあたりの推定行数は次のとおりです。

\[N_r = 100 部屋/ホテル \times 730 日 = 73,000 行\]

パーティションあたりの行数が比較的少ないため、あまり問題になることはありませんが、より多くの在庫日数を保存し始めたり、TTL を使用して在庫のサイズを適切に管理しなかったりすると、問題が発生し始める可能性があります。この大きなパーティションの分割を検討することもできます。その方法については後ほど説明します。

サイズ計算を実行するときは、行数などの変数について名目または平均的なケースを想定しがちです。成功したシステムでは、これらの種類の予測が実現することが多いため、最悪のケースも計算することを検討してください。

ディスク上のサイズの計算

パーティションのサイズを計算することに加えて、クラスターに保存する予定の各テーブルに必要なディスクスペースの量を推定することも非常に良いアイデアです。サイズを決定するには、次の式を使用してパーティションのサイズ St を決定します。

\[S_t = \displaystyle\sum_i sizeOf\big (c_{k_i}\big) + \displaystyle\sum_j sizeOf\big(c_{s_j}\big) + N_r\times \bigg(\displaystyle\sum_k sizeOf\big(c_{r_k}\big) + \displaystyle\sum_l sizeOf\big(c_{c_l}\big)\bigg) +\]
\[N_v\times sizeOf\big(t_{avg}\big)\]

これは前の式よりも少し複雑ですが、少しずつ分解してみましょう。最初に表記を見てみましょう。

  • この式では、ck はパーティションキー列、cs は静的列、cr は正規列、cc はクラスタリング列を指します。

  • tavg という用語は、タイムスタンプなど、セルごとに保存されるメタデータの平均バイト数を指します。この値には 8 バイトの見積もりを使用するのが一般的です。

  • 行数 Nr と値の数 Nv は、前の計算から認識できるでしょう。

  • sizeOf() 関数は、参照される各列の CQL データ型のバイト単位のサイズを指します。

最初の項では、パーティションキー列のサイズの合計を求めます。この例では、available_rooms_by_hotel_date テーブルには、単一のパーティションキー列である hotel_id があり、その型は text です。ホテルの識別子が単純な 5 文字コードであると仮定すると、5 バイトの値になるため、パーティションキー列サイズの合計は 5 バイトになります。

2 番目の項では、静的列のサイズの合計を求めます。このテーブルには静的列がないため、サイズは 0 バイトです。

3 番目の項は最も複雑であり、それには十分な理由があります。これは、パーティション内のセルのサイズを計算しているからです。クラスタリング列と正規列のサイズを合計します。2 つのクラスタリング列は、4 バイトの date と、2 バイトの短い整数である room_number で、合計 6 バイトになります。正規列は 1 つだけで、ブール型の is_available であり、サイズは 1 バイトです。正規列のサイズ (1 バイト) にクラスタリング列のサイズ (6 バイト) を加算すると、合計 7 バイトになります。項を完了するには、この値に行数 (73,000) を掛け、結果として 511,000 バイト (0.51 MB) になります。

4 番目の項は、Cassandra が各セルに保存するメタデータを単純にカウントしています。Cassandra 3.0 以降で使用されているストレージ形式では、特定のセルのメタデータの量は、保存されるデータの種類や、カスタムタイムスタンプまたは TTL 値が個々のセルに指定されているかどうかによって異なります。このテーブルの場合、前の計算から値の数 (73,000) を再利用し、8 を掛けると、0.58 MB になります。

これらの項を合計すると、最終的な見積もりは次のようになります。

\[パーティションサイズ = 16 バイト + 0 バイト + 0.51 MB + 0.58 MB = 1.1 MB\]

この式は、ディスク上のパーティションの実際のサイズの近似値ですが、非常に役立つほど正確です。パーティションは単一のノードに収まる必要があることを考えると、テーブル設計はディスクストレージに大きな負担をかけるようには見えません。

Cassandra のストレージエンジンは、SSTable ファイルの新しい形式を含む 3.0 リリースで再実装されました。以前の形式では、各セルのレコードの一部としてクラスタリング列の個別のコピーが保存されていました。新しい形式では、この重複が削除され、保存されたデータのサイズが縮小され、そのサイズを計算するための式が簡略化されます。

また、この見積もりでは、データの単一レプリカのみがカウントされていることに注意してください。ここで取得した値に、テーブルごとに必要な合計容量を決定するために、パーティション数とキースペースのレプリケーション戦略で指定されたレプリカ数を掛ける必要があります。これは、クラスターを計画するときに役立ちます。

大きなパーティションの分割

前述したように、目標は、単一のパーティションに触れるクエリ、またはそれが失敗する場合は、可能な限り最小限のパーティション数で必要なデータを提供できるテーブルを設計することです。ただし、例に示すように、Cassandra に組み込まれている制限に近づくワイドパーティションスタイルのテーブルを設計することは十分に可能です。テーブルでサイズ分析を実行すると、値の数、ディスク上のサイズ、またはその両方で、大きすぎる可能性のあるパーティションが明らかになる場合があります。

大きなパーティションを分割する手法は簡単です。パーティションキーに追加の列を追加するだけです。ほとんどの場合、既存の列の1つをパーティションキーに移動すれば十分です。別の方法としては、シャーディングキーとして機能する追加の列をテーブルに導入することもできますが、これには追加のアプリケーションロジックが必要になります。

利用可能な部屋の例を引き続き見ていくと、available_rooms_by_hotel_dateテーブルのパーティションキーにdate列を追加すると、各パーティションは特定の日付における特定のホテルの部屋の可用性を表すことになります。これにより、パーティションが大幅に小さくなることは確かですが、おそらく小さすぎるでしょう。連続する日のデータは別々のノードに置かれる可能性が高いためです。

バケット化と呼ばれる別の手法が、データを適度なサイズのパーティションに分割するためによく使用されます。たとえば、available_rooms_by_hotel_dateテーブルを、パーティションキーにmonth列(おそらく整数として表現)を追加することでバケット化できます。元の設計との比較を下の図に示します。month列はdateと部分的に重複していますが、大きくなりすぎないパーティションに関連データをグループ化するのに最適な方法を提供します。

image

どうしても広いパーティション設計を維持したい場合は、代わりにroom_idをパーティションキーに追加することもできます。これにより、各パーティションはすべての日付における部屋の可用性を表すことになります。特定の部屋の可用性を検索するクエリは特定されなかったため、最初または2番目の設計アプローチがアプリケーションのニーズに最も適しています。

資料は「Cassandra, The Definitive Guide」から引用。O’Reilly Media, Inc.発行。Copyright © 2020 Jeff Carpenter, Eben Hewitt。無断複写・転載を禁じます。許可を得て使用。