Sql-Server

手動創建索引碎片

  • April 21, 2020

有沒有人有一個很好的方法來手動創建索引的特定碎片,理想情況下不增加基礎表中的行數?我需要這個來進行索引重建基準測試。為了測量指定同一表/索引的碎片率所需的時間,我必須重新創建我想嘗試的特定碎片級別。

使用或多或少的隨機表更新來創建這種碎片非常耗時且困難。有任何想法嗎?

更新:這是我的測試表。它實際上有大約 540K 行,

USE [Test]
GO

/****** Object:  Table [dbo].[tFrag2]    Script Date: 12/22/2015 15:33:51 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[tFrag2](
   [a] [int] NULL,
   [b] [varchar](1000) COLLATE Latin1_General_CI_AS NULL,
   [c] [varchar](1000) COLLATE Latin1_General_CI_AS NULL,
   [d] [decimal](18, 0) NULL,
   [e] [int] NULL,
   [uid] [uniqueidentifier] NOT NULL,
   [dt1] [datetime] NULL,
   [dt2] [datetime] NULL,
   [dt3] [datetime] NULL,
   [dt4] [datetime] NULL,
   [dt5] [datetime] NULL,
   [dt6] [datetime] NULL,
   [dt7] [datetime] NULL,
   [dt8] [datetime] NULL,
   [dt9] [datetime] NULL,
   [nv1] [nvarchar](4000) COLLATE Latin1_General_CI_AS NULL,
   [nv2] [nvarchar](4000) COLLATE Latin1_General_CI_AS NULL,
   [nv8] [nvarchar](4000) COLLATE Latin1_General_CI_AS NULL,
   [nv3] [nvarchar](4000) COLLATE Latin1_General_CI_AS NULL,
   [nv4] [nvarchar](4000) COLLATE Latin1_General_CI_AS NULL,
   [nv5] [nvarchar](4000) COLLATE Latin1_General_CI_AS NULL,
   [nv6] [nvarchar](4000) COLLATE Latin1_General_CI_AS NULL,
   [nv7] [nvarchar](4000) COLLATE Latin1_General_CI_AS NULL,
   [lfd] [int] IDENTITY(1,1) NOT NULL,
CONSTRAINT [PK_tFrag2] PRIMARY KEY CLUSTERED 
(
   [uid] 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

SET ANSI_PADDING OFF
GO

ALTER TABLE [dbo].[tFrag2] ADD  CONSTRAINT [DF_tFrag2_a]  DEFAULT ((123123)) FOR [a]
GO

ALTER TABLE [dbo].[tFrag2] ADD  CONSTRAINT [DF_tFrag2_b]  DEFAULT ('ccccccccccccccccccc4444444444444444444444444') FOR [b]
GO

ALTER TABLE [dbo].[tFrag2] ADD  CONSTRAINT [DF_tFrag2_c]  DEFAULT ('ffffffffffffffffffffffffffffffffffffffffffffffff') FOR [c]
GO

ALTER TABLE [dbo].[tFrag2] ADD  CONSTRAINT [DF_tFrag2_d]  DEFAULT ((7)) FOR [d]
GO

ALTER TABLE [dbo].[tFrag2] ADD  CONSTRAINT [DF_tFrag2_e]  DEFAULT ((777)) FOR [e]
GO

ALTER TABLE [dbo].[tFrag2] ADD  CONSTRAINT [DF_tFrag_uid2]  DEFAULT (newid()) FOR [uid]
GO

ALTER TABLE [dbo].[tFrag2] ADD  CONSTRAINT [DF_tFrag2_dt1]  DEFAULT (getdate()) FOR [dt1]
GO

ALTER TABLE [dbo].[tFrag2] ADD  CONSTRAINT [DF_tFrag2_dt2]  DEFAULT (getdate()) FOR [dt2]
GO

ALTER TABLE [dbo].[tFrag2] ADD  CONSTRAINT [DF_tFrag2_dt3]  DEFAULT (getdate()) FOR [dt3]
GO

ALTER TABLE [dbo].[tFrag2] ADD  CONSTRAINT [DF_tFrag2_dt4]  DEFAULT (getdate()) FOR [dt4]
GO

ALTER TABLE [dbo].[tFrag2] ADD  CONSTRAINT [DF_tFrag2_dt5]  DEFAULT (getdate()) FOR [dt5]
GO

ALTER TABLE [dbo].[tFrag2] ADD  CONSTRAINT [DF_tFrag2_dt6]  DEFAULT (getdate()) FOR [dt6]
GO

ALTER TABLE [dbo].[tFrag2] ADD  CONSTRAINT [DF_tFrag2_dt7]  DEFAULT (getdate()) FOR [dt7]
GO

ALTER TABLE [dbo].[tFrag2] ADD  CONSTRAINT [DF_tFrag2_dt8]  DEFAULT (getdate()) FOR [dt8]
GO

ALTER TABLE [dbo].[tFrag2] ADD  CONSTRAINT [DF_tFrag2_dt9]  DEFAULT (getdate()) FOR [dt9]
GO

ALTER TABLE [dbo].[tFrag2] ADD  DEFAULT ('xxxxxxxxxxxxxxxxxxxx') FOR [nv1]
GO

ALTER TABLE [dbo].[tFrag2] ADD  DEFAULT ('xxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyxx') FOR [nv2]
GO

ALTER TABLE [dbo].[tFrag2] ADD  DEFAULT ('xxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyxx') FOR [nv8]
GO

ALTER TABLE [dbo].[tFrag2] ADD  DEFAULT ('xxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyxx') FOR [nv3]
GO

ALTER TABLE [dbo].[tFrag2] ADD  DEFAULT ('xxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyxx') FOR [nv4]
GO

ALTER TABLE [dbo].[tFrag2] ADD  DEFAULT ('xxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyxx') FOR [nv5]
GO

ALTER TABLE [dbo].[tFrag2] ADD  DEFAULT ('xxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyxx') FOR [nv6]
GO

ALTER TABLE [dbo].[tFrag2] ADD  DEFAULT ('xxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyxx') FOR [nv7]
GO

對於一個索引,沒有。對於數據庫中的索引,是的:創建一個表並執行循環以創建一堆記錄並擴大數據庫。然後放下桌子。現在,縮小數據文件(根據 Paul Randal 的說法非常非常愚蠢)。

我很快就輸入了這個東西……這個傻瓜真的很管用,但是……很慢。有什麼想法嗎?

(dbo.FragStat 是查詢該表的分片值的視圖)

Create procedure dbo.fragIt
    @FragDest int = 10
as
SET Statistics IO OfF
SET Statistics Time OfF
SET nocount on

declare @fragPercent int = 0

declare @cntr int = 0
While @FragDest > @fragPercent 
Begin
   select @fragPercent = avg_fragmentation_in_percent from dbo.FragStat Where NameOfTable = 'tFrag2' AND ALLOC_unit_type_desc = 'IN_ROW_DATA'

   set @cntr = @cntr + DATEPART(MS, GETDATE()) + 1000
   Update tFrag2 SET nv1 = REPLICATE('X', 1000), nv2 = REPLICATE('Y', 1000), nv3 = REPLICATE('Y', 1000) 
   WHERE LFD = @cntr or LFD = @cntr + 135 OR LFD = @cntr + 240 OR LFD = @cntr + 545 OR LFD = @cntr + 657 OR LFD = @cntr + 784 OR LFD = @cntr + 854

End
print 'destination frag of ' + cast(@FragDest as varchar(3)) + ' reached: ' + cast(@fragPercent as varchar(3))

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