Apache Cassandra static column 介绍与实战
假設(shè)我們有這樣的場(chǎng)景:我們想在 Cassandra 中使用一張表記錄用戶(hù)基本信息(比如 email、密碼等)以及用戶(hù)狀態(tài)更新。我們知道,用戶(hù)的基本信息一般很少會(huì)變動(dòng),但是狀態(tài)會(huì)經(jīng)常變化,如果每次狀態(tài)更新都把用戶(hù)基本信息都加進(jìn)去,勢(shì)必會(huì)讓費(fèi)大量的存儲(chǔ)空間。為了解決這種問(wèn)題,Cassandra 引入了 static column。同一個(gè) partition key 中被聲明為 static 的列只有一個(gè)值的,也就是只存儲(chǔ)一份。
定義 static column
在表中將某個(gè)列定義為 STATIC 很簡(jiǎn)單,只需要在列的最后面加上 STATIC 關(guān)鍵字,具體如下:
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 兩個(gè)字段設(shè)置為 STATIC 了,這意味著同一個(gè) username 只會(huì)有一個(gè) email 和 encrypted_password 。
注意,不是任何表都支持給列加上 STATIC 關(guān)鍵字的,靜態(tài)列有以下限制。
1、如果表沒(méi)有定義 Clustering columns(又稱(chēng) Clustering key),這種情況是不能添加靜態(tài)列的。如下:
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,沒(méi)有定義 clustering column,不支持創(chuàng)建 Static columns。這是因?yàn)殪o態(tài)列在同一個(gè) partition key 存在多行的情況下才能達(dá)到最優(yōu)情況,而且行數(shù)越多效果也好。但是如果沒(méi)有定義 clustering column,相同 PRIMARY KEY 的數(shù)據(jù)在同一個(gè)分區(qū)里面只存在一行數(shù)據(jù),本質(zhì)上就是靜態(tài)的,所以沒(méi)必要支持靜態(tài)列。
2、如果建表的時(shí)候指定了 COMPACT STORAGE,這時(shí)候也不允許存在靜態(tài)列:
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"3、如果列是 partition key/Clustering columns 的一部分,那么這個(gè)列不能說(shuō)明為靜態(tài)列:
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"給靜態(tài)列的表插入數(shù)據(jù)
含有靜態(tài)列的表插入數(shù)據(jù)和正常表類(lèi)似,比如我們現(xiàn)在往 iteblog_users_with_status_updates 導(dǎo)入數(shù)據(jù):
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)我們成功的插入一條數(shù)據(jù)了。但是上面的插入語(yǔ)句做了兩件事:
- 所有 username 為 iteblog 數(shù)據(jù)中的 email 和 encrypted_password 都被設(shè)置為 iteblog_hadoop@iteblog.com 和 0x877e8c36efa827dbd4cafbc92dd90d76 了。
- 在 iteblog 所在的分區(qū)中新增了 body 內(nèi)容為 Learning Cassandra! 的記錄。
現(xiàn)在我們?cè)偻碇胁迦胍粭l數(shù)據(jù),如下:
可以看到,這次插入數(shù)據(jù)的時(shí)候,我們并沒(méi)有指定 email 和 encrypted_password,但是從查詢(xún)結(jié)果可以看出,新增加的行 email 和 encrypted_password 的值和之前是一樣的!
現(xiàn)在由于某些原因,用戶(hù)修改了自己的 email,我們來(lái)看看會(huì)發(fā)生什么事:
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)從上面查詢(xún)這輸出的結(jié)果可以看出, username 為 iteblog 的 email 全部修改成一樣的了!這就是靜態(tài)列的強(qiáng)大之處。
現(xiàn)在表中存在了用戶(hù)的郵箱和密碼等信息,如果我們前端做了個(gè)頁(yè)面支持用戶(hù)修改自己的郵箱和密碼,這時(shí)候我們的后臺(tái)系統(tǒng)需要獲取到現(xiàn)有的郵箱和密碼,具體如下:
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 | 0x877e8c36efa827dbd4cafbc92dd90d76iteblog | iteblog@iteblog.com | 0x877e8c36efa827dbd4cafbc92dd90d76(2 rows)可以看出,表中有多少行 username 為 iteblog 的數(shù)據(jù)將會(huì)輸出多少行郵箱和密碼,這肯定不是我們想要的。這時(shí)候我們可以在查詢(xún)的時(shí)候加上 DISTINCT 關(guān)鍵字,如下:
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 的數(shù)據(jù),最終都會(huì)顯示一行數(shù)據(jù)。注意,雖然我們加了 DISTINCT 關(guān)鍵字,但是 Cassandra 并不是將 username 為 iteblog 的數(shù)據(jù)全部拿出來(lái),然后再去重的,因?yàn)殪o態(tài)列本來(lái)在底層就存儲(chǔ)了一份,所以沒(méi)必要去重。
靜態(tài)列的意義
到這里,我們已經(jīng)了解了 Cassandra 中靜態(tài)列的創(chuàng)建、使用等。那靜態(tài)列有什么意義呢?因?yàn)?Cassandra 中是不支持 join 的,靜態(tài)列相當(dāng)于把兩張表進(jìn)行了 join 操作。
那什么時(shí)候建議使用靜態(tài)列呢?如果兩張表關(guān)聯(lián)度很大,而且我們經(jīng)常需要同時(shí)查詢(xún)這兩張表,那這時(shí)候就可以考慮使用靜態(tài)列了。
原文鏈接
本文為云棲社區(qū)原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。
總結(jié)
以上是生活随笔為你收集整理的Apache Cassandra static column 介绍与实战的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 五年,时间告诉我只有自己强大才是真的强大
- 下一篇: 这款神秘的移动端OCR引擎,如何做到“所