2017-04-12 63 views
1

我的主表Users存儲有關用戶的信息。我計劃將UserId字段作爲表格的主鍵。我完全控制了這些密鑰的創建和分配,並且我想確保以提供良好性能的方式分配密鑰。我該怎麼辦?主表最簡單的主鍵?

回答

3

您有幾種選擇:

1)最通用的解決方案是使用的UUID,如RFC 4122規定。

例如,您可能有一個存儲UUID的STRING(36)。或者,您可以將UUID存儲爲一對INT64或作爲BYTE(16)。使用UUID有一些缺陷,所以請閱讀answer的詳細信息。

2)如果你想節省一點空間,並且確信你的用戶少於幾十億,那麼你可以使用INT64,然後使用隨機數生成器來分配UserIds。您希望確保您的用戶少於幾十億的原因是因爲Birthday Problem,一旦您擁有4B用戶,至少有一次碰撞的可能性大約爲50%,並且從那裏增加得非常快。如果您分配的UserId已分配給以前的用戶,那麼您的插入事務將失敗,因此您需要爲此做好準備(通過在生成新的隨機數後重試事務)。

3)如果在用戶表中有一列,您希望將其作爲主鍵(可能是因爲您知道您需要頻繁查找使用此列的條目),但是您不是肯定有關本專欄引起熱點的傾向(比如,因爲它是按順序生成的或基於時間戳生成的),那麼你有兩個選項:

3a)你可以「加密」MyColumn並將其用作主鍵。用數學術語來說,你可以對關鍵值使用自變量,這樣會產生混沌擾亂的效果,但仍然不會多次分配相同的值。在這種情況下,根本不需要單獨存儲MyColumn,而是隻存儲/使用加密版本,並且可以在應用程序代碼中對其進行必要的解密。請注意,這種加密不需要安全,只需要保證原始值的位以可逆方式充分加擾。例如:如果您的MyColumn值是按順序分配的整數,則可以顛倒MyColumn的位以創建充分加密的主鍵。如果您有更有趣的用例,可以使用加密算法,如XTEA

3b)有一個複合主鍵,其中第一部分爲ShardId,計算爲hash(MyColumn) % numShards,第二部分爲MyColumn。散列函數將確保您不會通過將行分配給單個拆分來創建熱點。關於這種方法的更多信息可以在here找到。請注意,您不需要使用加密哈希,儘管md5或sha512是很好的函數。 SpookyHash也是一個不錯的選擇。選擇正確數量的分片是一個有趣的問題,可以取決於您實例中的節點數量;它實際上是避免熱點的能力(更多碎片)和讀取/掃描效率(碎片更少)之間的一種折衷。如果你只有3個節點,那麼8個碎片可能是好的。如果你有100個節點,那麼32個碎片是一個合理的值來嘗試。

+0

謝謝。 1.您使用什麼算法計算分片計數 2.哈希(MyColumn)是128位長度,並且在nodejs中,我怎樣才能%numShards。我唱節點-int64,但它與64位整數。 – Chipintoza

+1

沒有計算碎片計數的單一算法。這是避免熱點(更多碎片)和讀取/掃描效率(更少碎片)之間的折衷。假設你的Cloud Spanner節點數量很少,那麼可能從8或16個分片開始? JavaScript使哈希困難,因爲它只支持53位整數(我認爲?)。這個頁面有一些你可以手動實現的散列函數:http://erlycoder.com/49/javascript-hash-functions-to-convert-string-int-integer-hash-一個更好的想法可能是使用一個衆所周知的算法(如md5),但截斷結果爲32位整數。 –

+0

謝謝,我在做同樣的事情,將結果截斷爲32位整數,它工作的很好。根據我的理解,關於碎片的數量可以從您的經驗中獲得建議。 – Chipintoza