2013-08-30 16 views
2

我正在將相當多的數據導入SQL Server數據庫。源數據來源於PgSql(包括表格定義),我通過一些相當簡單的正則表達式轉換爲TSql。這會創建沒有主鍵的表。是否添加主鍵導致重構底層數據

據我所知,缺少主鍵/集羣索引意味着數據存儲在堆中。

一旦導入完成後,我加的PK如下:

ALTER TABLE someTable ADD CONSTRAINT PK_someTable PRIMARY KEY (id); 

(注意缺乏CLUSTERED關鍵字)。現在發生了什麼?還是一堆?主鍵查找有什麼影響?這與添加標準索引有什麼不同嗎?

現在,而不是說我加的PK如下:

ALTER TABLE someTable ADD CONSTRAINT PK_someTable PRIMARY KEY CLUSTERED (id); 

我認爲這已經完全重構表到基於行的結構與PK,但不太理想的插入特性更加有效的查找。

我的假設是否正確?

如果我的導入按PK順序插入數據,首先省略PK有沒有好處?

+0

你想插入行,然後你要添加的PK? –

+0

我也可以做,但考慮到數據量,我寧願瞭解發生的情況,而不是花5-8小時測試不同的情況。我可以在鍵之前或之後添加鍵,但插入**將以鍵盤順序發生。 – spender

+1

如果目標表是HEAP,INSERT *應該更快。但是具有PK(非羣集)的HEAP表的總體(插入,更新,刪除,選擇)性能應該比羣集表的性能差。看看這個[SQL Server最佳實踐文章](http://technet.microsoft.com/en-us/library/cc917672.aspx)。如果你導入大量的數據,你應該看看[table partitioning(SQL2005 +)](http://msdn.microsoft.com/en-US/library/ms345146%28v=SQL.90%29#sql2k5parti_topic24 )。 –

回答

3

當你執行

ALTER TABLE someTable ADD CONSTRAINT PK_someTable PRIMARY KEY (id); 

如果在someTable沒有聚集索引,然後的PK將是一個集羣PK。否則,如果在執行ALTER .. ADD ... PRIMARY KEY (id)之前有聚集索引,則PK將是非聚集PK。

- 測試#1

BEGIN TRAN; 
CREATE TABLE dbo.MyTable 
(
    id INT NOT NULL, 
    Col1 INT NOT NULL, 
    Col2 VARCHAR(50) NOT NULL 
); 
SELECT i.name, i.index_id, i.type_desc 
FROM sys.indexes i 
WHERE i.object_id = OBJECT_ID(N'dbo.MyTable'); 
/* 
name index_id type_desc 
---- ----------- --------- 
NULL 0   HEAP 
*/ 
ALTER TABLE dbo.MyTable 
ADD CONSTRAINT PK_MyTable PRIMARY KEY (id); 

SELECT i.name, i.index_id, i.type_desc 
FROM sys.indexes i 
WHERE i.object_id = OBJECT_ID(N'dbo.MyTable'); 
/* 
name  index_id type_desc 
----------- ----------- --------- 
PK_MyTable 1   CLUSTERED 
*/ 
ROLLBACK; 

- 測試#2

BEGIN TRAN; 
CREATE TABLE dbo.MyTable 
(
    id INT NOT NULL, 
    Col1 INT NOT NULL, 
    Col2 VARCHAR(50) NOT NULL 
); 
SELECT i.name, i.index_id, i.type_desc FROM sys.indexes i WHERE i.object_id = OBJECT_ID(N'dbo.MyTable'); 
/* 
name index_id type_desc 
---- ----------- --------- 
NULL 0   HEAP 
*/ 
CREATE CLUSTERED INDEX ix1 
ON dbo.MyTable(Col1); 

SELECT i.name, i.index_id, i.type_desc FROM sys.indexes i WHERE i.object_id = OBJECT_ID(N'dbo.MyTable'); 
/* 
name index_id type_desc 
---- ----------- --------- 
ix1 1   CLUSTERED 
*/ 

ALTER TABLE dbo.MyTable 
ADD CONSTRAINT PK_MyTable PRIMARY KEY (id); 

SELECT i.name, i.index_id, i.type_desc FROM sys.indexes i WHERE i.object_id = OBJECT_ID(N'dbo.MyTable'); 
/* 
name  index_id type_desc 
---------- ----------- ------------ 
ix1  1   CLUSTERED 
PK_MyTable 2   NONCLUSTERED 
*/ 
ROLLBACK; 
+1

很棒的回答。如果可以,我會+2。謝謝。 – spender

+0

關於我最後一個問題的想法? – spender

1

在SQL服務器,主鍵默認爲羣集如果沒有聚集索引存在。聚集索引真的意味着「索引」不是保存在單獨的存儲區域(非聚集索引),而是索引數據與相應的常規表數據「散佈」。如果你對此有所瞭解,你會意識到它們只能是1個羣集索引。

聚集索引的真正優點是數據接近索引數據,因此您可以在驅動器頭處於「在該區域中」時抓取這兩個數據。當您正在處理的數據具有參考的局部性時,聚集索引比非混合索引快得多 - 當幾乎相同的值的行傾向於同時讀取時。

例如,如果您的主鍵是SSN,除非您正在處理關於SSN隨機排序的數據,否則您不會獲得很大的優勢 - 儘管由於數據接近性您確實獲得了優勢。但是,如果您可以通過SSN預設輸入,則集羣密鑰是一個很大的優勢。

所以是的,聚集索引會對數據進行重新排序,以便聚集索引。

+0

由於數據庫是多用戶的事實,事情從來沒有像我說得那麼簡單。但是,在處理髮票等事情時,如果發票項目將發票號碼作爲有聲索引的一部分,則一次獲取所有訂單項通常會變得更快。 –

0

感謝您的主題很好的演示!

上面的結論是不是錯了,但是它顯示了索引的結構,而不是表格的結構。我想下面的SQL將顯示信息爲實際的表:

select 
    o.name, 
    o.object_id, 
    case 
     when p.index_id = 0 then 'Heap' 
     when p.index_id = 1 then 'Clustered Index/b-tree' 
     when p.index_id > 1 then 'Non-clustered Index/b-tree' 
    end as 'Type' 
from sys.objects o 
inner join sys.partitions p on p.object_id = o.object_id 
where o.name = 'MyTable'; 

你會看到MyTable的是集羣:

name object_id Type 
------- ----------- ------------------- 
MyTable 1237579447 Clustered Index/b-tree 
相關問題