最基礎(chǔ)的primary key(The basic primary key)
我們從最基礎(chǔ)table開始,他們可以被稱為“靜態(tài)表”或“實(shí)體表”,用于存儲單個數(shù)據(jù)記錄。下面這個例子來源KillrVideo的一個例子程序。
`CREATE TABLE videos (
videoid uuid,
userid uuid,
name varchar,
description varchar,
location text,
location_typeint,
preview_thumbnails map<text,text>,
tags set<varchar>,
added_date timestamp,
PRIMARY KEY (videoid)
);
`
上面的PRIMARY KEY是最簡單的組成行式。區(qū)分出上傳到我們系統(tǒng)每個不同的video就是通過這個單一的參數(shù)作為唯一標(biāo)識。前面的PRIMARY KEY的第一個元素我們稱之為分區(qū)鍵。分區(qū)鍵在Apache Cassandra中有一個特殊作用,除了顯示數(shù)據(jù)庫中記錄的唯一性。另一個作用是,確定在分布式系統(tǒng)中數(shù)據(jù)的存放位置。
當(dāng)數(shù)據(jù)寫入到集群中的時候,第一步就是用hash函數(shù)計(jì)算partition key的值。
這個計(jì)算后的hash值將決定這條數(shù)據(jù)存放在哪個數(shù)據(jù)節(jié)點(diǎn)(或者replicas)上面。Apache Cassandra使用的算法是Murmur3,它將采取任意輸入并返回固定范圍內(nèi)的(當(dāng)前集群的結(jié)點(diǎn)有對應(yīng)的)值。
注:分區(qū)鍵屬于一個節(jié)點(diǎn)。 Cassandra被組織成一個節(jié)點(diǎn)簇,每個節(jié)點(diǎn)具有相等的分區(qū)密鑰散列。想象一下,我們有一個四節(jié)點(diǎn)Cassandra集群。在下面的示例集群中,節(jié)點(diǎn)1負(fù)責(zé)分區(qū)密鑰哈希值在0-24范圍;節(jié)點(diǎn)2負(fù)責(zé)分區(qū)密鑰哈希值25-49范圍等,如下圖:

簡而言之,分區(qū)鍵始終會對應(yīng)集群中一個節(jié)點(diǎn),并且該分區(qū)鍵上對應(yīng)的數(shù)據(jù)將始終可以在該節(jié)點(diǎn)上找到。
為什么這么重要呢?如果我們不能直接定位到分區(qū)鍵上對應(yīng)的數(shù)據(jù),那么為了查詢到你的數(shù)據(jù),我們必須檢索集群中的每個節(jié)點(diǎn)。在一個很小集群中,他可能很快的完成檢索,但是在一個非常大的集群環(huán)境中,要完成這個檢索就會很費(fèi)時。下面的圖表能更好的展示我們想表達(dá)的東西:

復(fù)合主鍵(Complex primary key)
Apache Cassandra中的另一種表格就是我們所說的“動態(tài)表格”。讓我們先來看看KillrVideo的另一個例子:
CREATE TABLE user_videos (
userid uuid,
added_date timestamp,
videoid uuid,
name text,
preview_image_location text,
PRIMARY KEY (userid, added_date, videoid)
);
在這張表中,我們能查詢到‘顯示與特定用戶相關(guān)的所有視頻’。正如你看到的那樣,這個PRIMARY KEY有多個分區(qū)鍵,我們現(xiàn)在添加了多個成分(elements)。
在分區(qū)鍵之后列出的所有列稱為聚簇列(clustering columns)。這是我們和關(guān)系型數(shù)據(jù)庫中有著很大不同的地方。分區(qū)鍵決定數(shù)據(jù)存放在哪個節(jié)點(diǎn)上,而聚簇列(clustering columns)決定了數(shù)據(jù)在該節(jié)點(diǎn)分區(qū)內(nèi)排列的順序。對于這個PRIMARYkey,我們讀這個的方法是從左到右講解:
[if !supportLists]l[endif]第一個元素是分區(qū)鍵
[if !supportLists]l[endif]第二元素是聚簇列(clustering columns),added_date字段是一個時間戳,因此排序順序按時間順序升序排列。
[if !supportLists]l[endif]第三元素是第二個聚簇列(clustering columns),由于videoid是一個UUID,所以我們將它包括在內(nèi)以便簡單地表明它是唯一記錄的一部分。
在插入數(shù)據(jù)之后,您期望您的查詢結(jié)果按照在單個分區(qū)內(nèi)按added_date字段的升序來返回?cái)?shù)據(jù)。

控制聚簇列的順序(Controlling order of the clustering columns)
由于聚簇列決定單個分區(qū)中的順序,因此對控制排序的方向性會有很大的幫助。我們可以通過向我們的SELECT中添加一個ORDER BY子句來完成這個時間排序查詢,如下所示:
SELECT *
FROM user_videos
WHERE userid = 522b1fe2-2e36-4cef-a667-cd4237d08b89
ORDER BY added_date DESC;
假如我們想將一些字段的排序順序給定一個默認(rèn)值呢?我們可以在創(chuàng)建表的時候使用CLUSTERING ORDER BY子句來指定:
CREATE TABLE user_videos (
userid uuid,
added_date timestamp,
videoid uuid,
name text,
preview_image_location text,
PRIMARY KEY (userid, added_date, videoid)
) WITH CLUSTERING ORDER BY (added_date DESC, videoid ASC);
現(xiàn)在,當(dāng)我們將數(shù)據(jù)插入到user_videos表時,數(shù)據(jù)已經(jīng)預(yù)先按added_date字段作降序排列了。

這可能看起來像是一個預(yù)優(yōu)化,但是這種使用的用例非常引人注目。當(dāng)在時間序列數(shù)據(jù)模型中使用ORDER BY時,我們現(xiàn)在可以快速訪問插入的最后N條數(shù)據(jù)。舉個例子:
SELECT *
FROM user_videos
WHERE userid = 522b1fe2-2e36-4cef-a667-cd4237d08b89
LIMIT 10;
當(dāng)我們查詢‘用戶上傳的最后10個視頻’時,通過簡單添加CLUSTERING ORDER BY子句,就可以實(shí)現(xiàn)非常快速,有用且高效的查詢。這在用戶交互或欺詐用例的情況下使用非常有用。
總結(jié)(Conclusion)
在這個關(guān)于PRIMARY KEY的快速概述中,我希望你看到主鍵KEY不但對你的查詢很重要,而且對于你如何存儲你的數(shù)據(jù)也是如此。對組件的一些基本理解可以幫助您在設(shè)計(jì)下一個數(shù)據(jù)模型中做出明智的選擇。例如,現(xiàn)在您已經(jīng)了解了分區(qū)鍵控制數(shù)據(jù)的位置后,所以最好不要只使用一個分區(qū)了!一個極端的例子就是,你可以輕松的做出一個基于Cassandra的程序而且你不須要知道其背后的原理?,F(xiàn)在您已經(jīng)知道Cassandra數(shù)據(jù)建模中最重要的知識了,那么您將如何處理它?