Sql-Server

堆是完全沒有索引還是沒有聚集索引的表?

  • August 19, 2016

BOL 似乎將堆定義為沒有聚集索引的表。

但是許多線上文章似乎將堆等同於沒有任何索引的表。

有什麼我不知道的微妙之處嗎?

謝謝

您需要非常小心您在網際網路上閱讀的內容;-)(當然,這也適用於這個答案或幾乎任何地方的任何內容,但仍然如此)。正如那裡有很多好的資訊一樣,也有很多錯誤資訊(遺憾的是,這不僅限於技術資訊)。人們複製和粘貼/轉發/分享兩者。所以,問這個問題很好:-)。

儘管 BOL 確實有一些錯誤,但在這種情況下(和大多數情況下)它是正確的:堆特別是沒有聚集索引的表。它與非聚集索引無關。當然,這可能是誤解了這些“線上文章”中所說的內容的簡單案例,因為“沒有任何索引的表”堆,但僅僅是因為沒有索引意味著沒有聚集索引。但是,如果這些文章聲稱只有非聚集索引的表不是堆,那麼它們肯定是不正確的。

如果您看一下,sys.indexes您會看到index_idof1是一個聚集索引並且0是一個堆。一個表將有一個或另一個。不可能兩者兼得。非聚集索引從index_id2 開始並從那裡上升。所有表都將有一個 index_id01一個或多個index_id>= 2

您甚至可以使用以下查詢對此進行測試:

SELECT COUNT(*)
FROM   sys.indexes si
WHERE  si.index_id IN (0, 1)
GROUP BY si.[object_id]
HAVING   COUNT(*) > 1;

它永遠不應該返回一行。

這是第二個測試,它更加明顯,不允許有人推測該條件可能存在但不存在,我認為上面的測試可以做到這一點:

-- DROP TABLE #tmp;
CREATE TABLE #tmp (Col1 INT, Col2 INT);
SELECT * FROM tempdb.sys.indexes si WHERE si.[object_id] = OBJECT_ID(N'tempdb.dbo.#tmp')
-- 1 row; index_id = 0 and type_desc = HEAP

CREATE NONCLUSTERED INDEX [IX_#tmp] ON #tmp (Col2 ASC);
SELECT * FROM tempdb.sys.indexes si WHERE si.[object_id] = OBJECT_ID(N'tempdb.dbo.#tmp')
-- 2 rows; index_id = 0 / HEAP and index_id = 2 / NONCLUSTERED

CREATE CLUSTERED INDEX [CIX_#tmp] ON #tmp (Col1 ASC);
SELECT * FROM tempdb.sys.indexes si WHERE si.[object_id] = OBJECT_ID(N'tempdb.dbo.#tmp')
-- still 2 rows (not 3!!); index_id = 1 / CLUSTERED and index_id = 2 / NONCLUSTERED

第二個測試的重點是,關於 SQL Server 的正確與否權威始終是 SQL Server 本身。因此,重要的是測試本質上是向 SQL Server 提問,而不是向人類提問。即使是專家有時也會出錯,但 SQL Server 總是正確的(當然,關於 SQL Server 的問題)。


此外,雖然這不是任何明確的“證據”,但以下 MSDN 頁面的標題相當有說服力:

堆(沒有聚集索引的表)

引用自:https://dba.stackexchange.com/questions/146858