理解newid()和newsequentialid()

原文地址:http://blog.csdn.net/xushichang/article/details/4390957 數據庫

1.:newsequentialid 函數比起 newid 函數最大的好處是:若是你在一個 UNIQUEIDENTIFIER 字段上創建索引,使用 newid 產生的新的值是不固定的,因此新的值致使索引B+樹的變化是隨機的。而 newsequentialid 產生的新的值是有規律的,則索引B+樹的變化是有規律的。有規律和無規律就會帶來性能的改進。windows

 

2:UNIQUEIDENTIFIER作主鍵(Primary Key)是一件很方便的事情,在數據合併等操做中有不可替代的優點
可是因爲普通的GUID的分散性使得若是主鍵加上彙集索引(Clustered Index)會致使在插入記錄時效率大大下降

SQL SERVER 2005中新增了一個NEWSEQUENTIALID的函數,MSDN的解釋是:
在指定計算機上建立大於先前經過該函數生成的任何 GUID 的 GUID。
NEWSEQUENTIALID() 不能在查詢中引用。
注:即只能作爲數據庫列的DEFAULT VALUE,不能執行相似SELECT NEWSEQUENTIALID()的語句
只有當計算機沒有網卡時,NEWSEQUENTIALID() 生成的 GUID 纔在該特定計算機中是惟一的。
注:這句話是錯誤的,應該是隻有隻有當計算機有網卡時,生成的GUID纔是全球惟一
您可使用 NEWSEQUENTIALID() 生成 GUID 以減小葉級別索引上的頁爭用。api

 

使用例子:ide

create table #dd
(
fid uniqueidentifier NULL  DEFAULT (NEWSEQUENTIALID()),
 fname [nvarchar](20))函數

 

insert into #dd(fname)values('dddff')性能

 

select * from #dd where fid > 'D8407C7D-0E7C-DE11-94B0-001A4DDD5F17' and fid<'E2507993-0E7C-DE11-94B0-001A4DDD5F17'測試

 

 

可是使用NEWSEQUENTIALID卻不是那麼一路順風
1. 如何得到生成的GUID
若是生成的GUID所在字段作爲外鍵要被其餘表使用,咱們就須要獲得這個生成的值
一般,PK是一個IDENTITY字段,咱們能夠在INSERT以後執行 SELECT SCOPE_IDENTITY()來得到新生成的ID
可是因爲NEWSEQUENTIALID()不是一個INDETITY類型,這個辦法是作不到了,而他自己又只能在默認值中使用,不能夠事先SELECT好再插入,那麼咱們如何獲得呢?有如下兩種方法:ui

--1. 定義臨時表變量 
DECLARE @outputTable TABLE(ID uniqueidentifier)
INSERT INTO TABLE1(col1, col2)
OUTPUT INSERTED.ID INTO @outputTable
VALUES('value1', 'value2')
SELECT ID FROM @outputTable

--2. 標記ID字段爲ROWGUID(一個表只能有一個ROWGUID)
INSERT INTO TABLE1(col1, col2)
VALUES('value1', 'value2')
--在這裏,ROWGUIDCOL其實至關於一個別名
SELECT ROWGUIDCOL FROM TABLE1


2. 如何設定DEFAULT VALUE爲NEWSEQUENTIALID()
經過UI的方式設定默認值時,因爲SQL SERVER 2005的BUG(即便是SP2也沒有解決),致使咱們設置了默認值爲NEWSEQUENTIALID()保存時會出現如下錯誤:
Warning were encountered during the pre-save validation process, and might result in a failure during save. Do you want to continue attempting to save?
'Table1' Table
-Error validating the default for column 'Id'
有兩種方式能夠解決:要麼直接點Yes,要麼經過CREATE TABLE語句來建表。

經過客戶端的方式,也能夠經過調用windows api產生sequential的guid,雖然說能夠省去上面提到的兩種麻煩,可是通過我測試,效果不是那麼好。
我創建了一個表有ID和TIMESTAMP兩個字段,用NEWSEQUENTIALID()和客戶端兩種方法生成記錄,並按ID和TIMESTAMP兩種方式進行排序。
NEWSEQUENTIALID()版本的結果永遠同樣。而客戶端生成就有一些問題,若是連續運行程序,表現良好,若是間隔一段時間後繼續運行,新生成的記錄就不必定大於以前生成的記錄,而每次間隔之間連續運行的部分,仍然表現良好。
客戶端生成sequential guid代碼以下spa

 1     public static class SequentialGuid
 2     {
 3        [DllImport("rpcrt4.dll", SetLastError = true)]
 4        static extern int UuidCreateSequential(out Guid guid);
 5
 6        public static Guid NewGuid()
 7        {
 8            const int RPC_S_OK = 0;
 9
10            Guid guid;
11            int result = UuidCreateSequential(out guid);
12            if (result != RPC_S_OK)
13           {
14                throw new ApplicationException("Create sequential guid failed: " + result);
15            }
16
17            return guid;
18        }
19    }
相關文章
相關標籤/搜索