我應該將前端生成的 UUIDv6 轉換為 binary(16) 以在 SQL Server 中用作集群主鍵嗎?
背景
根據前端開發人員的建議,我研究了在我們的新系統中使用 UUID 作為一堆表的主鍵。從學習隨機 UUID 與順序 UUID 的優缺點,到結合使用非聚集主鍵和可排序類型的聚集索引,我的研究向我指出了UUIDv6及其實現。
它能夠生成如下所示的 UUID(即順序的):
UUIDv1 UUIDv6 ------------------------------------ ------------------------------------ 5714f720-1268-11e7-a24b-96d95aa38c32 1e712685-714f-6720-a23a-c90103f70be6 68f820c0-1268-11e7-a24b-96d95aa38c32 1e712686-8f82-60c0-ac07-7d6641ed230d 7ada38f0-1268-11e7-a24b-96d95aa38c32 1e712687-ada3-68f0-93f8-c1ebf8e6fc8c 8cc06fd0-1268-11e7-a24b-96d95aa38c32 1e712688-cc06-6fd0-a828-671acd892c6a 9ea6a6b0-1268-11e7-a24b-96d95aa38c32 1e712689-ea6a-66b0-910c-dbcdb07df7a4
我認為 SQL Server 會很樂意在集群主鍵(唯一標識符)列中為我排序。
我幾乎不知道 SQL Server 如何對 uniqueidentifier 列進行排序。這是升序排序結果:
UUIDv6 唯一標識符已排序 ------------------------------------ 1e712688-cc06-6fd0- a828-67 **1acd892c6a** 1e712686-8f82-60c0- ac07-7d **6641ed230d** 1e712687-ada3-68f0-93f8- **c1** ebf8e6fc8c 1e712685-714f-6720-a23a- **c9** 0103f70be6 1e712689-ea6a-66b0-910c- **db** cdb07df7a4
這會導致碎片,就像使用隨機 UUID 一樣。這篇文章解釋了它們實際上是如何排序的。
真正的問題
幸運的是,該系統仍在開發中。接下來我應該選擇哪些選項?
- 重新排序字節,使最高/最低有效字節位於 SQL Server 期望的位置
UUIDv6 UUIDv6 重新排序的字節 ------------------------------------ ------------------------------------ 1e712685-714f-6720-a23a-c90103f70be6 c90103f7-0be6-a23a-6720- **1e712685** 714f 1e712686-8f82-60c0-ac07-7d6641ed230d 7d6641ed-230d- **ac07-60c0-1e712686** 8f82 1e712687-ada3-68f0-93f8-c1ebf8e6fc8c c1ebf8e6-fc8c-93f8-68f0- **1e712687** ada3 1e712688-cc06-6fd0-a828-671acd892c6a 671acd89-2c6a-a828-6fd0- **1e712688** cc06 1e712689-ea6a-66b0-910c-dbcdb07df7a4 dbcdb07d-f7a4-910c- **66b0-1e712689** ea6a
- 將 UUIDv6 轉換為二進制(16)並改用它
UUIDv6 UUIDv6 二進制(16) ------------------------------------ -------------------------------- 1e712685-714f-6720-a23a-c90103f70be6 **1e712685** 714f6720a23ac90103f70be6 1e712686-8f82-60c0-ac07-7d6641ed230d **1e712686** 8f8260c0ac077d6641ed230d 1e712687-ada3-68f0-93f8-c1ebf8e6fc8c **1e712687** ada368f093f8c1ebf8e6fc8c 1e712688-cc06-6fd0-a828-671acd892c6a **1e712688 cc066fd0a828671a** cd892c6a 1e712689-ea6a-66b0-910c-dbcdb07df7a4 **1e712689** ea6a66b0910cdbcdb07df7a4
有問題
option 1
UUID 標准在 ID 中嵌入了一個 4 位版本欄位。UUIDv6(仍然是非標準的)也遵循該規則。我將重新排序它們的方式將打破這一點。
有問題
option 2
我不知道。除了這個,幾乎找不到任何人在談論它,這與這個想法背道而馳。在使用 binary(16) 類型時我還應該注意其他陷阱嗎?
謝謝!
重新排序字節,使最高/最低有效字節位於 SQL Server 期望的位置
去做。
選項 1 是 SQL Server 原生使用 NEWSEQUENTIALID() 所做的,正如維基百科所說
NEWSEQUENTIALID 函式返回類似於 UUID 的 128 位標識符,這些標識符承諾按順序升序,直到下次系統重新啟動
在 SQL Server 中,UNIQUEIDENTIFIER 只是一個 128 位二進制類型。它不需要符合 UUID 的結構。
如果它是按順序生成的*,您可以將其設為聚集索引鍵。擁有一個更窄的聚集索引鍵通常不值得擁有一個額外且不必要的索引的成本。
*如果順序值的排序順序中的位置偶爾發生變化或由幾個不同的應用程序伺服器在幾個不同的地方生成,這不是什麼大問題。