此文根據用友的文件《基於SQL Server 2008構建SOA大型管理軟體技術實踐》“翻譯”而成,非原創。在baidu上看見此文,覺得寫的很好,就將原先的PPT細化一下併除去廢話。
第一篇講的是主鍵的選擇。
我就不廢話int32和guid主鍵的優缺點了,這是他的PPT說明。
用友採用的是long作為主鍵,這是原始PPT上的話:
為實現不同站點間能夠互相交換資料,必須保證站點間主鍵不串號,所以在最前端用兩位是站點編號,理論上是100個, 這個問題應該不大,但是我在想,兩個站點如果是集團內部可以協商使用不同的編號,如果是兩個集團之間呢?思考中,有點挑刺了。
不知道你注意到沒有,他的年是三位,這樣就可以節省一位,當然,我覺得可以再改進,將日期轉化為數字更好,可以參考 datetime的Second實現:
{
get
{
return (int) ((this.InternalTicks / 0x989680L) % 60L);
}
}
這個是精確到秒的,可以想辦法刪除到日期。
為什麼要在第二個部分放上日期呢?我猜想是希望資料被儲存後,能夠按照順序存放,而不至於像GUID那樣作為聚集索引後,資料插入時經常挪動位置(SQL Server新提供的建立GUID已經解決這個問題)。但是我覺得加入日期還是有問題的,這要看後面的順序號。
最後一部分是順序號,根據PPT說明,應該是採用儲存過程獲取序號,但是我在想,某個日期在申請一個序號後,必須記錄已經用到哪個序號,而且是區分不同日期。(快取也一樣),這樣就必須為每個日期建立獨立的行儲存序列號,如果整個資料庫公用一個序列,我想一年也就365條記錄無所謂,但是如果每個表獨立序列,就是4000*365條記錄(U9 大約4000張表),那對於效能要求高的序列運算,似乎不妥。
我的觀點:
我覺得U9的主鍵設計是很不錯的設計。當然,我們可以站在巨人的肩膀上繼續改進。
我覺得他在規劃段時,U9使用了十進位制的概念,應該使用十六進位制更好,有利於充分利用資源;
應刪除日期的部分,而改成後面全部是序號,這樣就只用為每個表維護一個序列計數器了。
我的實踐
在我參與設計的ERP中,為提高主鍵的效能,採用了以下措施:
1、使用int32的序列,一個表對應一個獨立的序列,減少序列表的行數量。當然,沒有考慮多站點的情況;
2、獲取序列的API被設計成批量獲取,例如:IEnumerable<int> GetSeq(int count),例如在儲存某個單據時,你(Application)很清楚需要多少個新的序列值,這樣可以批量而減少往返;
3、使用獨立的應用程式服務處理序列,並採用類似買發票的原理來處理快取、離線應用,原理是:應用伺服器獲取一段(1000個)序列,並迅速儲存結果到資料庫,當客戶端不斷申請序列時,應用伺服器並不需要寫入資料而是直接在記憶體中扣減,如果出現斷電,那麼僅僅浪費一段編號而已。通過此方法解決了效能(使用快取)、負載均衡(使用單一序列伺服器)和離線應用(聯機時購買發票號)。此方案實際上是Oracle序列功能的改進版,因為SQL Server一直沒有提供此功能搞的我很鬱悶。