Quelqu'un a-t-il une bonne approche pour créer manuellement une fragmentation spécifique à un indice, idéalement sans augmenter le nombre de lignes dans la table sous-jacente? J'ai besoin de ceci à des fins d'un indice de référence de reconstruction. Afin de mesurer le temps requis pour les taux de fragmentation spécifiques de la même table/index, je dois ré-créer des niveaux de fragmentation spécifiques que je souhaite essayer.
Il est très prudent et difficile de créer cette fragmentation avec des mises à jour de la table plus ou moins de Ramdom. Des idées?
Mise à jour: C'est ma table de test. Il a en fait environ 540 000 rangées,
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
Pour un index, non. Pour les index dans une base de données, oui: Créez une table et faites une boucle pour créer un tas d'enregistrements et développer la base de données. Puis déposez la table. Maintenant, rétrécissez le fichier de données ( très très stupide selon Paul Randal ).
La fragmentation se produit lorsque le moteur de stockage ne peut pas placer physiquement une ligne dans sa position logique correcte. Vous avez donc besoin d'une table sans espace interne, puis insérez des rangées dans le "milieu".
Le moyen le plus simple de remplir des pages consiste à assurer une seule rangée conviendra
create table T (
id int, -- primary key & clustered; fill factor 100%
c1 char (5000) not null -- fixed length, over half the size of a page
)
Écrivez autant de lignes que vous avez besoin; Quelques centaines de mille devraient le faire. Gardez l'identifiant séquentiel pour éviter la fragmentation d'une telle étape. Laissez toutefois des lacunes pour de nouvelles valeurs.
Insérez maintenant des lignes pour obtenir la fragmentation souhaitée. Générez de manière aléatoire les valeurs d'identification entre le courant MIN et Max. Cela peut être fait de manière itérative ou sage en sélectionnant le haut n des lignes actuelles et incrémentation de l'ID pour s'adapter aux lacunes réservées.
Un nombre de lignes cible peut être obtenu en commençant par un ensemble initial plus petit ou en supprimant des rangées de manière aléatoire.
J'ai rapidement tapé cette chose ... Cette ventouse fonctionne vraiment, mais ... est lente. Des pensées?
(DBO.FRAGSTAT est une vue qui interroge la valeur de fragmentation de cette table)
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))