认识SQL Server的虚影行(Ghost record)
2016-01-28 20:20
507 查看
目录
目录什么是SQL Server的虚影行
认识并维护虚影行
虚影行存在的坏处
参考资料
什么是SQL Server的虚影行
在SQL Server中,为了加快数据的删除与数据删除后的回滚操作,对含有索引的表引入了数据的逻辑删除,即数据先被标记为删除,再进行物理删除。这些被标记删除,而还未执行物理删除的记录行,则被称为虚影行,即ghost record(又被称为ghost row)Row in the leaf level of an index that has been marked for deletion, but has not yet been deleted by the database engine.
下图所示是SSMS中某个表虚影行的信息,
索引属性->碎片选项->虚影行数:
认识并维护虚影行
实际上SQL Server的虚影行由后台线程:ghost_cleanup自主维护。为了更清晰的理解上述内容,我们做如下演示:创建一张含聚集索引的表并插入5000条记录,然后通过trace flags禁用后台线程ghost_cleanup,再删除表中所有记录后,最终观察记录行数的变化及影响。
首先,我们创建一个测试数据库mydb
[code]USE master GO --创建一个测试数据库 CREATE DATABASE mydb; GO
然后在这个库中,创建一张含有5000条记录的聚集索引表ghosttest:
[code]--创建一个测试表ghosttest CREATE TABLE ghosttest( id int identity(1,1) NOT NULL , fname nvarchar(20) NOT NULL, lname nvarchar(50) NULL ) --在字段id上创建聚集索引 CREATE CLUSTERED INDEX id ON ghosttest ( id ) --循环插入5000条记录 insert into ghosttest (fname, lname) values ('Hyper','Wang'); go 5000
然后我们通过trace flag(661)禁用ghost record维护的相关线程:ghost_cleanup:
[code]--打开661全局标记,禁用ghost record维护的相关线程 DBCC TRACEON (661,-1) GO --查询当前trace flag状态 DBCC TRACESTATUS ----------------------------------------------- TraceFlag Status Global Session 661 1 1 0
接着我们删除聚集索引表ghosttest上的所有记录:
[code]--delete表中的所有记录 DELETE FROM ghosttest; --查询当前记录数 SELECT * FROM dbo.ghosttest --------------------------------------------------
最终我们可通过如下sql,查询表ghosttest的虚影行数为5000行。
注意DB与表的参数
[code]--查询表ghosttest的虚影行数 SELECT OBJECT_NAME(object_id) AS Name ,record_count ,GHOST_RECORD_COUNT FROM sys.dm_db_index_physical_stats(DB_ID(N'mydb'), OBJECT_ID('ghosttest'), NULL, NULL, 'DETAILED') ----------------------------------------------- Name record_count GHOST_RECORD_COUNT ghosttest 0 5000 ghosttest 25 0
虚影行存在的坏处
通过上述内容,我们已经知道SQL Server存在虚影行,而且这个虚影行由后台线程自主维护。如上述,虚影行存在可加快表中记录的删除与记录删除后的回滚,但是虚影行的存在也有坏处:虚影行(Ghost record)会影响SQL Server的统计信息的预估,从而影响sql语句的整个执行计划。在清空表ghosttest记录后,我们执行select语句,并查看IO的统计信息与实际执行计划:
[code]--打开IO统计信息,并执行select语句 SET STATISTICS IO ON; SELECT * FROM dbo.ghosttest ----------------------------------------------- (0 row(s) affected) 表 'ghosttest'。扫描计数 1,逻辑读取 27 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
注意:逻辑读取27次
同时,我们可能看到执行计划中预估信息:5000行
当我们开启ghost record相关线程后,我们再次执行select语句
[code]--开启ghost record相关线程 DBCC TRACEOFF(661,-1); --打开IO统计信息,并执行select语句 SET STATISTICS IO ON; SELECT * FROM dbo.ghosttest ----------------------------------------------- (0 row(s) affected) 表 'ghosttest'。扫描计数 1,逻辑读取 2 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
我们可以看到,此时的逻辑读取已经由原来的27变为2。注意,本文虽然使用了聚集索引表进行说明,但对于含有非聚集索引的堆表同样存在虚影行,因此在我们使用SQL Server的过程中,我们需尽可能的降低虚影行带来的负面影响。对于高更改(即增/删/改)的堆表,个人建议在合适列上添加聚集索引(Clustered index)。
参考资料
Glossary – SQL Server 2008 R2https://msdn.microsoft.com/en-us/library/ms165911%28d=printer,v=SQL.105%29.aspx
Tuning options for SQL Server when running in high performance workloads
https://support.microsoft.com/en-us/kb/920093
文章收藏地址:
/article/3721849.html
相关文章推荐
- Mysql
- 测试必备技能系列1 :通过mysql命令进行脚本数据导入
- Oracle经典教程(推荐)
- MongoDB
- MySql中的事务
- 学习MongoDB 二:MongoDB加入、删除、改动
- MYSQL 创建数据库语句
- mybatis解析日期时遭遇旧版本mysql日期默认值的问题
- Oracle Meger Into
- Oracle忘记密码时
- MySQL之Master-Master配置
- memcached Java Client
- Oracle基础(五):多表查询
- Redis
- Mysql配置为Master/Slave的常用维护命令
- mysql(zip)安装和基本命令
- SQL JOINS
- mysql 存储过程
- Autosqli——一个sqlmapapi的web管理应用
- MySQL数据库事务隔离级别(Transaction Isolation Level)