Sql-Server
堆是完全沒有索引還是沒有聚集索引的表?
BOL 似乎將堆定義為沒有聚集索引的表。
但是許多線上文章似乎將堆等同於沒有任何索引的表。
有什麼我不知道的微妙之處嗎?
謝謝
您需要非常小心您在網際網路上閱讀的內容;-)(當然,這也適用於這個答案或幾乎任何地方的任何內容,但仍然如此)。正如那裡有很多好的資訊一樣,也有很多錯誤資訊(遺憾的是,這不僅限於技術資訊)。人們複製和粘貼/轉發/分享兩者。所以,問這個問題很好:-)。
儘管 BOL 確實有一些錯誤,但在這種情況下(和大多數情況下)它是正確的:堆特別是沒有聚集索引的表。它與非聚集索引無關。當然,這可能是誤解了這些“線上文章”中所說的內容的簡單案例,因為“沒有任何索引的表”是堆,但僅僅是因為沒有索引意味著沒有聚集索引。但是,如果這些文章聲稱只有非聚集索引的表不是堆,那麼它們肯定是不正確的。
如果您看一下,
sys.indexes
您會看到index_id
of1
是一個聚集索引並且0
是一個堆。一個表將有一個或另一個。不可能兩者兼得。非聚集索引從index_id
2 開始並從那裡上升。所有表都將有一個 index_id0
或1
一個或多個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 頁面的標題相當有說服力: