2009-09-10 129 views
0

我有一系列有關SQL,SQL 2005中的鍵,索引和約束的問題。我一直在使用SQL大約4年,但我從來沒有能夠獲得有關此主題的明確答案,並且博客文章中總是存在矛盾的信息等。我創建和使用的大多數時間表都只有一個Identity列是主鍵,其他表通過外鍵指向它。SQL 2005:鍵,索引和約束問題

在連接表中,我沒有標識並在外鍵列上創建複合主鍵。以下是我對當前信仰的一系列陳述,這可能是錯誤的,如果是這樣,請糾正我,以及其他問題。

所以這裏有雲:

據我瞭解一個聚集和非聚集索引的區別(不管它是唯一與否)是聚集索引會影響表中的數據的物理順序(因此在表中只能有一個),而非聚集索引構建樹數據結構。在創建索引時,爲什麼我應該關心「羣集」與「非羣集」?我應該什麼時候使用其中一種?我被告知插入和刪除非聚集索引很慢,因爲樹需要「重建」。我認爲聚集索引不會以這種方式影響性能?

我看到主鍵實際上只是聚集索引是唯一的(他們必須被聚集?)。主鍵與集羣唯一索引有什麼特別之處?

我也見過約束,但我從來沒有用過它們或真的看過它們。有人告訴我,約束的目的是爲了強制數據完整性,而索引是針對性能的。我也讀過約束作爲索引來實現,因此它們是「相同的」。這聽起來不錯,對我來說。約束如何與索引不同?

回答

2

正如你所說的那樣,Clustered indexes是關於如何在物理上存儲表中的數據的定義,即,你有一個使用集羣密鑰排序的B樹,並且在葉級別有數據。

Non-clustered indexes另一方面是分離的樹結構,它們在葉級別只有聚簇鍵(或者如果表是堆的話就是RID),這意味着當你使用非聚簇索引時,使用聚集索引來獲取其他列(除非您的請求已完全由非聚集索引覆蓋,如果您僅請求構成非聚集索引鍵列的列,則會發生這種情況)。

什麼時候應該使用其中一種?那麼,因爲你只能有一個聚集索引,所以在最有意義的列上定義它,即當你大多數時候通過ID查找客戶端時,在ID上定義一個聚集索引。非聚簇索引應該在較少使用的列上定義。

關於性能,更改索引鍵的插入或更新通常是痛苦的,無論它是否在非聚簇索引上被凍結,因爲頁面拆分可能發生,這會迫使數據在頁面之間移動(移動頁面聚集索引的傷害更大,因爲葉級中有更多數據)。因此,一般規則是避免改變索引鍵並插入新值,以便它們是順序的。否則,你會遇到碎片,並將不得不定期重建你的索引。

最後,關於約束,根據定義,它們與索引無關,但SQL服務器已選擇使用索引來實現它們。例如。目前,唯一的約束被實現爲索引,但是這可以在未來的版本中改變(儘管我懷疑這會發生)。索引的類型(聚類與否)取決於您,請記住您只能有一個聚簇索引。

如果您還有其他問題,我強烈建議您閱讀this book,其中涵蓋了這些主題。

0

我沒有時間深入回答這個問題,所以這裏是我的頭頂部的一些信息:

你說得對聚集索引。他們根據聚集索引的排序順序重新排列物理數據。您可以專門爲範圍限制查詢使用聚簇索引(例如,在日期之間)。

PK默認情況下是聚簇的,但它們不一定是。這只是一個默認設置。 PK應該是該行的UID。

約束可以實現爲索引(例如,唯一約束),但也可以實現爲默認值。

1

主鍵是一個邏輯概念在關係數據庫理論中 - 這是一個關鍵(通常也是一個索引),旨在唯一標識您的任何行。因此它必須是唯一的,它不能爲NULL。

集羣密鑰是專門針對SQL Server的存儲物理概念。這是一個不僅用於查找等的特殊索引,還定義了表中數據的物理結構。在西歐文化的印刷電​​話簿中(除冰島外),聚集索引將是「LastName,FirstName」。

由於羣集索引定義了您的物理數據佈局,您只能擁有其中一個(或者沒有 - 不推薦,但是)。

的聚集鍵

的要求是:

  • 必須是唯一的(如果沒有,SQL Server將增加一個4字節的 「uniqueifier」)
  • 應該是穩定的(永不改變)
  • 應儘可能小(INT最好)
  • 應該是不斷增加的(認爲:IDENTITY)

SQL服務器,使您的主密鑰t他默認集羣密鑰 - 但如果需要,您可以更改密鑰。另外,請注意:組成集羣密鑰的列將被添加到表中每個非聚集索引的每個條目 - 因此您希望儘可能小地保留您的集羣關鍵字。這是因爲集羣密鑰將用於執行「書籤查找」 - 如果您在非集羣索引中找到了一個條目(例如,根據他們的社會安全號碼發現某人),現在您需要將整行數據獲取更多詳細信息,您需要執行查找,爲此,使用集羣密鑰。

有什麼牌子好或有用的羣集和/或主鍵的大辯論 - 這裏有幾個優秀的博客文章來了解這個:

Marc

1

您有幾個問題。我會打破其中一些:

當創建索引爲什麼我應該關心羣集與非羣集?

有時你會在意如何組織行。這取決於你的數據以及你將如何使用它。例如,如果您的主鍵是uniqueidentifier,您可能不希望它是CLUSTERED,因爲GUID值本質上是隨機的。這將導致SQL在整個表中隨機插入行,從而導致頁面拆分,從而損害性能。如果您的主鍵值總是按順序遞增(例如,int IDENTITY),那麼您可能希望它是CLUSTERED,因此您的表總是會在最後增長。

默認情況下,主鍵爲CLUSTERED,大多數情況下您不必擔心它。

有人告訴我,插入和刪除非聚集索引很慢,因爲樹需要「重建」。我認爲聚集索引不會以這種方式影響性能?

實際上,情況正好相反。 NONCLUSTERED索引作爲單獨的數據結構保存,但結構設計爲允許進行一些修改而不需要「重新構建」。索引最初創建時,您可以指定FILLFACTOR,該索引指定在索引的每個頁面上留出多少可用空間。這允許索引在需要分頁之前容忍一些修改。即使在發生頁面拆分時,它也只會影響相鄰頁面,而不會影響整個索引。

同樣的行爲適用於CLUSTERED指標,但由於CLUSTERED索引存儲實際的表數據,對索引頁分割操作可以更加昂貴,因爲整行可能需要被移動(而不是隻對鍵列和ROWIDNONCLUSTERED索引中)。

FILLFACTOR和頁面拆分下面的MSDN頁會談: http://msdn.microsoft.com/en-us/library/aa933139(SQL.80).aspx

有什麼特殊的一個主鍵VS一個聚集唯一索引? 約束與索引有何不同?

對於這兩個我認爲這是更多關於宣佈你的意圖。當您致電PRIMARY KEY時,您聲明它是識別給定行的主要方法。 PRIMARY KEYCLUSTERED UNIQUE INDEX物理上不同嗎?我不確定。行爲本質上是一樣的,但是對於使用數據庫的人來說,您的意圖可能並不明確。

關於約束,有許多類型的約束。對於UNIQUE CONSTRAINT,除了聲明你的意圖之外,它和UNIQUE INDEX之間沒有什麼區別。還有其他類型的約束不會直接映射到某種索引,如CHECK約束,DEFAULT約束和FOREIGN KEY約束。