Sql-Server

在 SQL Server 中將堆更改為聚群表時會發生什麼?

  • June 1, 2021

據我了解,堆是一個無序的對象。當您插入一條記錄時,SQL Server 使用 IAM 頁面來獲取屬於該堆的頁面,並使用 PFS 頁面找到一個有足夠空間容納該記錄並插入其中的特定頁面。

當您在其上創建聚集索引時,它就變成了聚集表,而聚集索引本身也變成了表。但是由於聚集索引和原始堆是兩種不同的結構,SQL Server 是否會創建一個新結構(聚集索引)並將所有內容從幫助移動到新結構然後丟棄堆?

可以在表上定義很多東西,比如觸發器、約束、權限等。如果我的假設是正確的,這意味著 SQL Server 也會將所有這些東西移動到新結構中。我在文件中沒有找到任何相關資訊。我的理解正確嗎?

是的,當您在堆上創建聚集索引時,所有行都已排序移動到新的聚集索引。使用新的聚集索引鍵作為行定位符來重建任何非聚集索引。

不過,它是同一張表,因此觸發器、約束等不必更改。

然而,反之亦然。當您在表上刪除聚集索引時,聚集索引的葉級頁面保留在原地,它們成為新的堆。當行定位器從 CI 鍵切換到 rowid (file:page:slot) 時,仍會重建非聚集索引。

可以在表上定義很多東西,比如觸發器、約束、權限等。如果我的假設是正確的,這意味著 SQL Server 也會將所有這些東西移動到新結構中。我在文件中沒有找到任何相關資訊。我的理解正確嗎?

正確,一切都移至新結構

object_id表保持不變,並且權限也自動“移動”(實際上它們沒有移動但保持不變,因為它們object_id保持不變)

使用下面的 T-SQL 進行測試:

-- use any db to test   
use TestDB


-- create a Heap   
create table TestHeap (ID int identity, tName varchar(10))  

insert into TestHeap (tName)   
values ('aaaaa'),('bbbbb'),('ccccc')


-- check the object_id and type_desc   
select * from sys.indexes where [object_id] = object_id('TestHeap')     


-- create a test user   
create user TestHeapUser without login

grant select on TestHeap to TestHeapUser


-- select from table as test user    
execute as user = 'TestHeapUser'
select * from TestHeap
revert


-- let's turn the table into clustered index   
create clustered index CIX_ID on TestHeap (ID)


-- see if object_id changed (it is not), and type_desc turned into "CLUSTERED"   
select * from sys.indexes where [object_id] = object_id('TestHeap')     


-- test permissions again  (object_id has not changed so Test user still should have permissions!)   
execute as user = 'TestHeapUser'
select * from TestHeap
revert


-- lets turn table into Heap again   
drop  index CIX_ID on TestHeap

-- test permissions again  (object_id has not changed so Test user still should have permissions!)   
execute as user = 'TestHeapUser'
select * from TestHeap
revert

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