データはどのように書き込まれるか

DataStax Enterpriseデータベースがどのようにデータの書き込みと格納を行っているか理解する。

DataStax Enterpriseデータベースは、書き込みの即時ロギングから始まり、ディスクへのデータの書き込みが終わるまで、書き込みパスの複数の段階でデータを処理します。

  1. コミット・ログへのデータのログ記録
  2. memtableへのデータの書き込み
  3. memtableからのデータのフラッシュ
  4. ディスク上のSSTableへのデータの格納
注: すべての書き込みのタイムスタンプはUTC(協定世界時)です。

書き込みのログ記録とmemtableへの保存

書き込みが発生すると、データベースはデータをmemtableと呼ばれるメモリー構造に格納します。構成可能な永続性を提供するために、データベースはディスクのコミット・ログにも追加書き込みします。commitlog_syncsyncに設定されていると、コミット・ログはノードに対して行われたすべての書き込みを受け取ります。これらの永続書き込みは、ノードで電源が故障した場合でも永続的に存続します。memtableは、データベースがキーで検索するデータ・パーティションのライトバック・キャッシュです。memtableは構成可能な制限に達するまでソートされた順序で書き込みを格納し、その後でフラッシュされます。

memtableからのデータのフラッシュ

データをmemtableからフラッシュするために、データベースはmemtableのソート順にデータをディスクに書き込みます。トークンをディスク上の場所にマップするパーティション・インデックスがディスク上に作成されます。

memtableの内容が構成可能なしきい値を超えるか、commitlog領域がcommitlog_total_space_in_mbを超えると、memtableは、ディスクにフラッシュされるキューに置かれます。フラッシュ対象データがmemtable_cleanup_thresholdを超えると(これは自動で計算されます)、データベースは次のフラッシュが成功するまで書き込みをブロックします。

nodetool flushまたはnodetool drainを使用すると、手動でテーブルをフラッシュできます(他のノードへの接続をリッスンせずにmemtableをフラッシュします)。コミット・ログのリプレイ時間を短縮するために、DataStaxでは、ノードを再起動する前にmemtableをフラッシュすることを推奨しています。ノードが停止した場合、コミット・ログをリプレイすると、停止前にそこにあったmemtableへの書き込みが復元されます。

コミット・ログ・セグメントのパージ

データベースはコミット・ログを使用して、起動時にmemtablesを再構築し、クラッシュ後に復元します。通常の操作中は、コミット・ログは、セグメントに分割されています。書き込みは順番に記録され、現在のセグメントがcommitlog_segment_size_in_mbに達すると、新しいセグメントが作成されます。データベースは、セグメント内のすべてのデータがmemtableからディスクにフラッシュされた後にのみ、コミット・ログ・セグメントをパージします。コミット・ログ・ディレクトリーが最大サイズ(commitlog_total_space_in_mb)に達すると、最も古いセグメントがパージされ、対応するテーブルがディスクにフラッシュされます。

たとえば、以下の2つのテーブルがあるとします。
  • スループットが非常に高いテーブルA
  • スループットが非常に低いテーブルB

すべてのコミット・ログ・セグメントには、システム・テーブルのほか、テーブルAとBの両方の書き込みが含まれています。テーブルAのmemtableはすぐに満杯になり、頻繁にフラッシュされます。一方、テーブルBのmemtableは満杯になるまで時間がかかり、フラッシュされることはほとんどありません。コミット・ログが最大サイズに達すると、テーブルBのmemtableが強制的にフラッシュされ、セグメントがパージされます。

テーブルBは、何百もの小さなSSTableではなく、大きなチャンクにフラッシュされます。コミット・ログ領域とmemtable領域が等しい場合は、テーブルAがフラッシュされるたびに、テーブルBのmemtableが(小さくはなりますが)フラッシュされます。要約すると、複数のテーブルがある場合は、コミット・ログ・セグメント用に大きな領域を確保した方がよいでしょう。

ディスク上のSSTableへのデータの格納

memtableとSSTableは、テーブルごとに維持されます。コミット・ログはテーブル間で共有されます。SSTableは不変であり、memtableがフラッシュされた後に再度書き込まれることはありません。この結果、パーティションは通常、複数のSSTableファイルにわたって格納されます。読み取り操作を支援するために他の多くのSSTable構造が存在します。

SSTableの名前とバージョン

SSTableとはディスクに格納されたファイルです。データ・ファイルはデータ・ディレクトリーに格納されますが、インストール時に場所が変わります。キー・スペースごとに、データ・ディレクトリー内のディレクトリーに各テーブルが格納されます。

たとえば、次のSSTableバージョンはaa、形式はbtiです。
data/cycling/cyclist_expenses-e4f31e122bc511e8891b23da85222d3d/aa-1-bti-Data.db
ここで、
  • cyclingは、ストリーミング・データまたは一括読み込みデータのキースペースを区別するキースペース名です。
  • cyclist_expensesはテーブル名で、この後にダッシュとテーブルの一意の識別子である16進数文字列(-e4f31e122bc511e8891b23da85222d3d)が続きます。
  • aaはSSTableのバージョンで、btiは形式です。この情報を使用して、SSTableに互換性があるDSEバージョンを決定します。「SSTableの互換性とアップグレード・バージョン」を参照してください。

データベースは各テーブルのサブディレクトリーを作成します。このサブディレクトリーから、シンボリック・リンク(symlink)を介して選択された物理ドライブまたはデータ・ボリュームを参照できます。パフォーマンスを向上させる場合は、この機能を使用することで、非常にアクティブなテーブルをSSDのような高速メディアに移動したり、接続されているすべてのストレージ・デバイスでテーブルを分配して、ストレージ層のI/Oバランスを改善したりすることが可能になります。

データベースは、SSTableごとに以下の構造体を作成します。

圧縮情報(CompressionInfo.db)
圧縮されていないデータの長さ、チャンク・オフセット、およびその他の圧縮に関する情報を保持するファイル
データ(Data.db)
SSTableデータ
ダイジェスト(Digest.crc32、Digest.adler32、Digest.sha1)
データ・ファイルのadler32チェックサムを保持するファイル
ブルーム・フィルター(Filter.db)
ディスク上のSSTableにアクセスする前にmemtableに行データが存在するかどうかを確認する、メモリーに格納された構造
パーティション・インデックス(Partitions.db)
行インデックス(Row.db)またはデータ・ファイル内のパーティション・レベルへのポインターを持つパーティション・キーのインデックス。
行インデックス(Row.db)
SSTable内のすべてのパーティションの行インデックスが含まれます。
統計(Statistics.db)
SSTableの内容についての統計メタデータ
CRC(CRC.db)
非圧縮ファイル内のチャンク用のCRC32を保持するファイル
SSTableの目次(TOC.txt)
SSTable TOCのすべてのコンポーネントのリストを格納するファイル
セカンダリ・インデックス(SI_.*.db)
組み込みセカンダリ・インデックス。SSTableごとに複数のSIが存在する可能性があります。