SQLSERVER中的鬼影索引

时间:2023-03-10 07:06:49
SQLSERVER中的鬼影索引

SQLSERVER中的鬼影索引

看这篇文章之前可以先看一下鬼影记录

了解了解一下SQLSERVER里的鬼影记录
关于鬼影记录的翻译一
关于鬼影记录的翻译二

当删除表中的某一条记录的时候,索引页面的对应记录并不是马上删除,而是标记为鬼影,当提交事务的时候才真正删除索引记录,

或者回滚事务,鬼影索引记录才会恢复为正常索引记录,这样做的目的就是提高了性能

鬼影索引只会出现在非聚集索引页,聚集索引页是没有鬼影索引的


建立环境

 --ghost index record
USE [pratice]
GO
--建表
CREATE TABLE testghostindexnoncluster(id INT IDENTITY(1,1),NAME VARCHAR(20))
GO
--插入记录
INSERT INTO testghostindexnoncluster(name)
SELECT '' UNION ALL
SELECT ''
GO CREATE INDEX IX_testghostindexnoncluster ON testghostindexnoncluster([Id] ASC) SELECT * FROM [dbo].[testghostindexnoncluster]
GO

SQLSERVER中的鬼影索引

 --TRUNCATE TABLE DBCCResult
INSERT INTO DBCCResult EXEC ('DBCC IND(pratice,testghostindexnoncluster,-1) ') SELECT * FROM [dbo].[DBCCResult] ORDER BY [PageType] DESC DBCC TRACEON(3604,-1)
GO
DBCC PAGE([pratice],1,15663,1) --索引页
GO

正常情况下的索引页面,Record Type = INDEX_RECORD

 DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。

 PAGE: (1:15663)

 BUFFER:

 BUF @0x03E53304

 bpage = 0x1A468000                   bhash = 0x00000000                   bpageno = (1:15663)
bdbid = 5 breferences = 0 bUse1 = 7847
bstat = 0xc0000b blog = 0x1212121b bnext = 0x00000000 PAGE HEADER: Page @0x1A468000 m_pageId = (1:15663) m_headerVersion = 1 m_type = 2
m_typeFlagBits = 0x0 m_level = 0 m_flagBits = 0x4000
m_objId (AllocUnitId.idObj) = 539 m_indexId (AllocUnitId.idInd) = 256
Metadata: AllocUnitId = 72057594073251840
Metadata: PartitionId = 72057594061062144 Metadata: IndexId = 2
Metadata: ObjectId = 1463676262 m_prevPage = (0:0) m_nextPage = (0:0)
pminlen = 13 m_slotCnt = 2 m_freeCnt = 8066
m_freeData = 135 m_reservedCnt = 0 m_lsn = (3046:350:12)
m_xactReserved = 0 m_xdesId = (0:11665608) m_ghostRecCnt = 0
m_tornBits = 0 Allocation Status GAM (1:2) = ALLOCATED SGAM (1:3) = ALLOCATED
PFS (1:8088) = 0x60 MIXED_EXT ALLOCATED 0_PCT_FULL DIFF (1:6) = CHANGED
ML (1:7) = NOT MIN_LOGGED DATA: Slot 0, Offset 0x7a, Length 13, DumpStyle BYTE Record Type = INDEX_RECORD Record Attributes =
Memory Dump @0x0849C07A 00000000: 06010000 00b52000 00010000 00††††††††...... ...... Slot 1, Offset 0x6d, Length 13, DumpStyle BYTE Record Type = INDEX_RECORD Record Attributes =
Memory Dump @0x0849C06D 00000000: 06020000 00b52000 00010001 00††††††††...... ...... OFFSET TABLE: Row - Offset
1 (0x1) - 109 (0x6d)
0 (0x0) - 122 (0x7a) DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。

SQLSERVER中的鬼影索引
我们删除id=1的记录

 SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
GO
BEGIN TRAN
DELETE FROM testghostindexnoncluster WHERE [id]=1
--ROLLBACK TRAN

再看一下索引页面

 DBCC TRACEON(3604,-1)
GO
DBCC PAGE([pratice],1,15663,1) --索引页
GO

SQLSERVER中的鬼影索引

 DATA:

 Slot 0, Offset 0x7a, Length 13, DumpStyle BYTE

 Record Type = GHOST_INDEX_RECORD     Record Attributes =
Memory Dump @0x0849C07A 00000000: 0a010000 00b52000 00010000 00††††††††...... ...... Slot 1, Offset 0x6d, Length 13, DumpStyle BYTE Record Type = INDEX_RECORD Record Attributes =
Memory Dump @0x0849C06D 00000000: 06020000 00b52000 00010001 00††††††††...... ...... OFFSET TABLE: Row - Offset
1 (0x1) - 109 (0x6d)
0 (0x0) - 122 (0x7a) DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。

SQLSERVER中的鬼影索引
可以看到第一行记录被标记为Record Type = GHOST_INDEX_RECORD

我们回滚事务

 ROLLBACK TRAN

恢复正常了,索引页面中第一行记录的Record Type = INDEX_RECORD

 DATA:

 Slot 0, Offset 0x94, Length 13, DumpStyle BYTE

 Record Type = INDEX_RECORD           Record Attributes =
Memory Dump @0x0849C094 00000000: 06010000 00b52000 00010000 00††††††††...... ...... Slot 1, Offset 0x6d, Length 13, DumpStyle BYTE Record Type = INDEX_RECORD Record Attributes =
Memory Dump @0x0849C06D 00000000: 06020000 00b52000 00010001 00††††††††...... ...... OFFSET TABLE: Row - Offset
1 (0x1) - 109 (0x6d)
0 (0x0) - 148 (0x94) DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
 DROP TABLE testghostindexnoncluster
GO

如有不对的地方,欢迎大家拍砖o(∩_∩)o