シナリオ
Cassandra テーブルに、ユーザー情報 (メールアドレスやパスワードなど) とユーザーのステータス更新が保存されているとします。一般的に、ユーザーのステータスが頻繁に変更される場合、ユーザー情報はほとんど変更されません。ユーザー情報が各ステータス更新とともに更新されると、大量のストレージ容量が使用されます。
Cassandra は、この問題を解決するために静的カラム機能を提供しています。同じパーティションキーで宣言されている静的カラムは、1 つの値のみを持ちます。これは、このカラムに 1 セットのデータのみが保存されることを示します。
静的カラムを定義する
カラム名を静的カラムとして定義するには、カラム名の末尾に STATIC を追加します。次の例を参照してください。
CREATE TABLE "iteblog_users_with_status_updates" (
"username" text,
"id" timeuuid,
"email" text STATIC,
"encrypted_password" blob STATIC,
"body" text,
PRIMARY KEY ("username", "id")
);
上記のコマンドは、email フィールドと encrypted_password フィールドの両方を STATIC に設定します。これは、username には 1 つの email 値と 1 つの encrypted_password 値のみがあることを示します。
静的カラムの制限
各テーブルのカラムに STATIC キーワードを追加することはできません。静的カラムには、次の制限があります。
クラスタリングカラム (クラスタリングキーとも呼ばれます) は、テーブルに定義されていません。次の例を参照してください。
cqlsh:iteblog_keyspace> CREATE TABLE "iteblog_users_with_status_updates_invalid" (
... "username" text,
... "id" timeuuid,
... "email" text STATIC,
... "encrypted_password" blob STATIC,
... "body" text,
... PRIMARY KEY ("username")
... );
InvalidRequest: Error from server: code=2200 [Invalid query] message="Static columns are only useful (and thus allowed) if the table has at least one clustering column"
iteblog_users_with_status_updates_invalid テーブルにはプライマリキーのみがあり、テーブルにクラスタリングカラムが定義されていないため、このテーブルに静的カラムを作成することはできません。同じパーティションキーのデータ行が多いほど、静的カラムのパフォーマンスが向上します。クラスタリングカラムが定義されていない場合、プライマリキー値はパーティション内の一意の行を識別し、静的カラムは必要ではありません。
テーブルは COMPACT STORAGE テーブルに設定されています。次の例を参照してください。
cqlsh:iteblog_keyspace> CREATE TABLE "iteblog_users_with_status_updates_invalid" (
... "username" text,
... "id" timeuuid,
... "email" text STATIC,
... "encrypted_password" blob STATIC,
... "body" text,
... PRIMARY KEY ("username", "id")
... )WITH COMPACT STORAGE;
InvalidRequest: Error from server: code=2200 [Invalid query] message="Static columns are not supported in COMPACT STORAGE tables"
パーティションキーまたはクラスタリングカラムの一部として使用されるカラムを STATIC に設定することはできません。次の例を参照してください。
cqlsh:iteblog_keyspace> CREATE TABLE "iteblog_users_with_status_updates_invalid" (
... "username" text,
... "id" timeuuid STATIC,
... "email" text STATIC,
... "encrypted_password" blob STATIC,
... "body" text,
... PRIMARY KEY ("username", "id")
... );
InvalidRequest: Error from server: code=2200 [Invalid query] message="Static column id cannot be part of the PRIMARY KEY"
cqlsh:iteblog_keyspace> CREATE TABLE "iteblog_users_with_status_updates_invalid" (
... "username" text,
... "id" timeuuid,
... "email" text STATIC,
... "encrypted_password" blob STATIC,
... "body" text,
... PRIMARY KEY (("username", "id"), email)
... );
InvalidRequest: Error from server: code=2200 [Invalid query] message="Static column email cannot be part of the PRIMARY KEY"
静的カラムを含むテーブルにデータを挿入する
静的カラムを含むテーブルへのデータの挿入は、標準テーブルへのデータの挿入と同様の方法で行います。たとえば、次の文を実行して、iteblog_users_with_status_updates テーブルにデータを挿入できます。
cqlsh:iteblog_keyspace> INSERT INTO "iteblog_users_with_status_updates"
... ("username", "id", "email", "encrypted_password", "body")
... VALUES (
... 'iteblog',
... NOW(),
... 'iteblog_hadoop@iteblog.com',
... 0x877E8C36EFA827DBD4CAFBC92DD90D76,
... 'Learning Cassandra!'
... );
cqlsh:iteblog_keyspace> select username, email, encrypted_password, body from iteblog_users_with_status_updates;
username | email | encrypted_password | body
----------+----------------------------+------------------------------------+---------------------
iteblog | iteblog_hadoop@iteblog.com | 0x877e8c36efa827dbd4cafbc92dd90d76 | Learning Cassandra!
(1 rows)
テーブルに 1 行のデータが挿入されます。上記の文は、次の 2 つの操作を実行しました。
iteblog ユーザー名の email カラムと encrypted_password カラムのすべてのデータが、iteblog_hadoop@iteblog.com と 0x877e8c36efa827dbd4cafbc92dd90d76 に設定されます。
Learning Cassandra! 本文の行が iteblog パーティションに追加されます。次の文を実行して、別の行をテーブルに挿入します。
cqlsh:iteblog_keyspace> INSERT INTO "iteblog_users_with_status_updates"
... ("username", "id", "body")
... VALUES ('iteblog', NOW(), 'I love Cassandra!') ;
cqlsh:iteblog_keyspace> select username, email, encrypted_password, body from iteblog_users_with_status_updates;
username | email | encrypted_password | body
----------+----------------------------+------------------------------------+---------------------
iteblog | iteblog_hadoop@iteblog.com | 0x877e8c36efa827dbd4cafbc92dd90d76 | Learning Cassandra!
iteblog | iteblog_hadoop@iteblog.com | 0x877e8c36efa827dbd4cafbc92dd90d76 | I love Cassandra!
(2 rows)
cqlsh:iteblog_keyspace>
この文は、テーブルにデータが挿入されるときに、email カラムと encrypted_password カラムが指定されていないことを示しています。ただし、クエリ結果を見ると、新しい行の 2 つのカラムの値は、上記の文で指定された値と同じです。
ユーザーは、何らかの理由でメールアドレスを変更します。次の例を参照してください。
cqlsh:iteblog_keyspace> UPDATE iteblog_users_with_status_updates SET email = 'iteblog@iteblog.com'
... WHERE username = 'iteblog';
cqlsh:iteblog_keyspace> select username, email, encrypted_password, body from iteblog_users_with_status_updates;
username | email | encrypted_password | body
----------+---------------------+------------------------------------+---------------------
iteblog | iteblog@iteblog.com | 0x877e8c36efa827dbd4cafbc92dd90d76 | Learning Cassandra!
iteblog | iteblog@iteblog.com | 0x877e8c36efa827dbd4cafbc92dd90d76 | I love Cassandra!
(2 rows)
クエリ結果を見ると、email カラムは静的であるため、iteblog ユーザー名のすべてのメールが新しいメールに変更されています。
テーブルには、メールアドレスやパスワードなどのユーザー情報が保存されています。ユーザーが フロントエンドページでメールアドレスとパスワードを変更した場合、バックエンドシステムは、次の文を実行して現在のメールアドレスとパスワードを取得する必要があります。
cqlsh:iteblog_keyspace> SELECT "username", "email", "encrypted_password"
... FROM "iteblog_users_with_status_updates"
... WHERE "username" = 'iteblog';
username | email | encrypted_password
----------+---------------------+------------------------------------
iteblog | iteblog@iteblog.com | 0x877e8c36efa827dbd4cafbc92dd90d76
iteblog | iteblog@iteblog.com | 0x877e8c36efa827dbd4cafbc92dd90d76
(2 rows)
iteblog ユーザー名のメールアドレスとパスワードのすべての行が返されます。この結果は予期されていません。SELECT DISTINCT 文を実行して、重複行を除外できます。
cqlsh:iteblog_keyspace> SELECT DISTINCT "username", "email", "encrypted_password"
... FROM "iteblog_users_with_status_updates"
... WHERE "username" = 'iteblog';
username | email | encrypted_password
----------+---------------------+------------------------------------
iteblog | iteblog@iteblog.com | 0x877e8c36efa827dbd4cafbc92dd90d76
(1 rows)
iteblog ユーザー名の重複行がすべて削除され、最終的に一意の行が表示されます。
Cassandra は、iteblog ユーザー名のすべてのデータに対して DISTINCT 操作を実行しません。これは、静的カラムデータのセットが基盤となるシステムに保存されているためです。