我知道,有些原因索引碎片是交易:更新和插入可能导致索引碎片,即使你回滚
非顺序插入 - 做一个非顺序插入,SQL Server会将〜50%时,从旧页面到新分配页面的数据。这会导致页面拆分,每页有大约50%来自旧页面的数据。
更新到具有更大价值的现有行的值,它不适合在同一页上
我听说即使你回滚事务,碎片仍然存在,但我找不到文档那。
是否有人有文档或者脚本来证明这一点?
我知道,有些原因索引碎片是交易:更新和插入可能导致索引碎片,即使你回滚
非顺序插入 - 做一个非顺序插入,SQL Server会将〜50%时,从旧页面到新分配页面的数据。这会导致页面拆分,每页有大约50%来自旧页面的数据。
更新到具有更大价值的现有行的值,它不适合在同一页上
我听说即使你回滚事务,碎片仍然存在,但我找不到文档那。
是否有人有文档或者脚本来证明这一点?
今天我做了一些测试,结果并不完全符合我的预期。
环境:
的Microsoft SQL Server 2008(SP2) - 10.0.4000.0(X64)2010年9月16日19时43分16秒版权所有(C)1988-2008微软公司企业版(64位)上Windows NT 6.0(Build 6002:Service Pack 2)
首先,我查找了一个已经有碎片的表。 令人惊讶的是,在我的DBA数据库中,我找到了一个名为tableSizeBenchmark的表。
USE [DBA]
GO
CREATE TABLE [dbo].[tableSizeBenchmark](
[lngID] [bigint] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
[dbName] [varchar](100) NOT NULL,
[tableName] [varchar](100) NOT NULL,
[creationDate] [smalldatetime] NOT NULL,
[numberOfRows] [bigint] NULL,
[spaceUsedMb] [numeric](18, 0) NULL,
CONSTRAINT [PK_tableSizeBenchmark] PRIMARY KEY CLUSTERED
(
[lngID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
ON [PRIMARY]
) ON [PRIMARY]
GO
USE [DBA]
GO
CREATE UNIQUE NONCLUSTERED INDEX [UIXtableSizeBenchmark] ON [dbo].[tableSizeBenchmark]
(
[dbName] ASC,
[tableName] ASC,
[creationDate] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF,
IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
这是分裂的水平之前进行任何测试:
你需要为了进行相同的测试,以创建这些程序2。 基本上我使用了随机字符串生成器和一个随机数生成器,只是因为我想插入10,000条记录,看看如何使分片变得更糟,然后在ROLLBACK事务中看到真实情况,如果碎片仍然存在或消失。
--DROP PROCEDURE GetRandomString
--GO
--DROP PROCEDURE GetRandomNumber
--GO
create procedure GetRandomString (@STR VARCHAR(100) OUTPUT)
as
begin
-- generates a random string
-- marcelo miorelli
-- 01-oct-2014
-- one of the other features that makes this more flexible:
-- By repeating blocks of characters in @CharPool,
-- you can increase the weighting on certain characters so that they are more likely to be chosen.
DECLARE @z INT
, @i INT
, @MIN_LENGTH INT
, @MAX_LENGTH INT
DECLARE @CharPool VARCHAR(255)
DECLARE @RandomString VARCHAR(255)
DECLARE @PoolLength INT
SELECT @MIN_LENGTH = 20
SELECT @MAX_LENGTH = 100
--SET @z = RAND() * (@max_length - @min_length + 1) + @min_length
SET @Z = 50
-- define allowable character explicitly - easy to read this way an easy to
-- omit easily confused chars like l (ell) and 1 (one) or 0 (zero) and O (oh)
SET @CharPool =
'abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ23456789.,[email protected]#%^&*'
SET @CharPool =
'ABCDEFGHIJKLMNPQRSTUVWXYZ'
SET @PoolLength = Len(@CharPool)
SET @i = 0
SET @RandomString = ''
WHILE (@i < @z) BEGIN
SELECT @RandomString = @RandomString +
SUBSTRING(@Charpool, CONVERT(int, RAND() * @PoolLength), 1)
SELECT @i = @i + 1
END
SELECT @STR = @RandomString
end
GO
create procedure GetRandomNumber (@number int OUTPUT)
as
begin
-- generate random numbers
-- marcelo miorelli
-- 01-oct-2014
DECLARE @maxval INT, @minval INT
select @maxval=10000,@minval=500
SELECT @Number = CAST(((@maxval + 1) - @minval) *
RAND(CHECKSUM(NEWID())) + @minval AS INT)
end
go
您已经创建了上述程序后,看到我来运行这个测试的代码如下:
SELECT object_id AS ObjectID,
object_NAME (Object_id) as Table_NAME,
index_id AS IndexID,
avg_fragmentation_in_percent AS PercentFragment,
fragment_count AS TotalFrags,
avg_fragment_size_in_pages AS PagesPerFrag,
page_count AS NumPages
FROM sys.dm_db_index_physical_stats(DB_ID('dba'),
NULL, NULL, NULL , 'DETAILED')
WHERE OBJECT_ID = OBJECT_ID('tableSizeBenchmark')
and avg_fragmentation_in_percent > 0
所以结果: 运行上面的脚本之后,但在回滚或提交,交易仍然是开放的:
请注意碎片有所增加。 在我们回滚这个事务之后,这个碎片是REMAIN还是DISAPPEAR?
让我也张贴在这里,我用它来看看碎片级别的脚本:
SELECT object_id AS ObjectID,
object_NAME (Object_id) as Table_NAME,
index_id AS IndexID,
avg_fragmentation_in_percent AS PercentFragment,
fragment_count AS TotalFrags,
avg_fragment_size_in_pages AS PagesPerFrag,
page_count AS NumPages
FROM sys.dm_db_index_physical_stats(DB_ID('dba'),
NULL, NULL, NULL , 'DETAILED')
WHERE OBJECT_ID = OBJECT_ID('tableSizeBenchmark')
and avg_fragmentation_in_percent > 0
这个实验的结果:
正如你所看到的,在交易之前,碎片化水平回到原来的状况。
希望这有助于
马塞洛
你尝试过什么?把一张表与索引放在一起。使用guid作为聚簇索引,使分段变得容易。添加约5k行,检查碎片。然后做你的插入和回滚,再次检查碎片。 – 2014-09-30 13:29:35