假設咱們有這樣的場景:咱們想在 Cassandra 中使用一張表記錄用戶基本信息(好比 email、密碼等)以及用戶狀態更新。咱們知道,用戶的基本信息通常不多會變更,可是狀態會常常變化,若是每次狀態更新都把用戶基本信息都加進去,勢必會讓費大量的存儲空間。爲了解決這種問題,Cassandra 引入了 static column。同一個 partition key 中被聲明爲 static 的列只有一個值的,也就是隻存儲一份。前端
在表中將某個列定義爲 STATIC 很簡單,只須要在列的最後面加上 STATIC 關鍵字,具體以下:oop
CREATE TABLE "iteblog_users_with_status_updates" ( "username" text, "id" timeuuid, "email" text STATIC, "encrypted_password" blob STATIC, "body" text, PRIMARY KEY ("username", "id") );
iteblog_users_with_status_updates 表中咱們將 email 和 encrypted_password 兩個字段設置爲 STATIC 了,這意味着同一個 username 只會有一個 email 和 encrypted_password 。ui
注意,不是任何表都支持給列加上 STATIC 關鍵字的,靜態列有如下限制。spa
一、若是表沒有定義 Clustering columns(又稱 Clustering key),這種狀況是不能添加靜態列的。以下:code
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 表只有 PRIMARY KEY,沒有定義 clustering column,不支持建立 Static columns。這是由於靜態列在同一個 partition key 存在多行的狀況下才能達到最優狀況,並且行數越多效果也好。可是若是沒有定義 clustering column,相同 PRIMARY KEY 的數據在同一個分區裏面只存在一行數據,本質上就是靜態的,因此不必支持靜態列。server
二、若是建表的時候指定了 COMPACT STORAGE,這時候也不容許存在靜態列:blog
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"
三、若是列是 partition key/Clustering columns 的一部分,那麼這個列不能說明爲靜態列:hadoop
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 導入數據:get
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)
咱們成功的插入一條數據了。可是上面的插入語句作了兩件事:it
如今咱們再往表中插入一條數據,以下:
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,可是從查詢結果能夠看出,新增長的行 email 和 encrypted_password 的值和以前是同樣的!
如今因爲某些緣由,用戶修改了本身的 email,咱們來看看會發生什麼事:
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)
從上面查詢這輸出的結果能夠看出, username 爲 iteblog 的 email 所有修改爲同樣的了!這就是靜態列的強大之處。
如今表中存在了用戶的郵箱和密碼等信息,若是咱們前端作了個頁面支持用戶修改本身的郵箱和密碼,這時候咱們的後臺系統須要獲取到現有的郵箱和密碼,具體以下:
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)
能夠看出,表中有多少行 username 爲 iteblog 的數據將會輸出多少行郵箱和密碼,這確定不是咱們想要的。這時候咱們能夠在查詢的時候加上 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)
這樣無論表中有多少行 username 爲 iteblog 的數據,最終都會顯示一行數據。注意,雖然咱們加了 DISTINCT 關鍵字,可是 Cassandra 並非將 username 爲 iteblog 的數據所有拿出來,而後再去重的,由於靜態列原本在底層就存儲了一份,因此不必去重。
到這裏,咱們已經瞭解了 Cassandra 中靜態列的建立、使用等。那靜態列有什麼意義呢?由於 Cassandra 中是不支持 join 的,靜態列至關於把兩張表進行了 join 操做。
那何時建議使用靜態列呢?若是兩張表關聯度很大,並且咱們常常須要同時查詢這兩張表,那這時候就能夠考慮使用靜態列了。
本文爲雲棲社區原創內容,未經容許不得轉載。