Here is the quickly baked test script:
DROP TABLE TestCalendar
CREATE TABLE [dbo].[TestCalendar](
[ID] [bigint] NOT NULL,
[N_Date] [datetime] NOT NULL,
[WeekDay] [smallint] NULL,
PRIMARY KEY (ID) WITH FILLFACTOR = 100
)
CREATE TABLE [dbo].[Tmp_TestCalendar](
[ID] [bigint] NOT NULL,
[N_Date] [datetime] NOT NULL,
[WeekDay] [int] NULL,
PRIMARY KEY (ID) WITH FILLFACTOR = 100
)
SET NOCOUNT ON
INSERT INTO dbo.TestCalendar ( ID, N_Date, WeekDay )
SELECT tg.N ID, DATEADD(dd, N, 0) N_Date, CONVERT(SMALLINT, n%7 +1 ) WeekDay
FROM Service.dbo.TallyGenerator(0, 50000, NULL, 1) tg
ORDER BY ID
WHILE EXISTS (SELECT * FROM dbo.TestCalendar T1
WHERE NOT EXISTS (SELECT * FROM dbo.[Tmp_TestCalendar] T2
WHERE T2.ID = T1.ID)
)
BEGIN
INSERT INTO dbo.Tmp_TestCalendar ( ID, N_Date, WeekDay )
SELECT TOP 1000 ID, N_Date, WeekDay
FROM dbo.TestCalendar T1
WHERE NOT EXISTS (SELECT * FROM dbo.[Tmp_TestCalendar] T2
WHERE T2.ID = T1.ID)
ORDER BY ID
END
DBCC SHOWCONTIG (TestCalendar) WITH ALL_INDEXES--, TABLERESULTS
DBCC SHOWCONTIG (Tmp_TestCalendar) WITH ALL_INDEXES--, TABLERESULTS
EXEC sys.sp_spaceused @objname = N'TestCalendar', @updateusage = 'true'
ALTER TABLE [dbo].TestCalendar ADD WeekDay_int int NULL;
EXEC sys.sp_spaceused @objname = N'TestCalendar', @updateusage = 'true'
GO
UPDATE [dbo].TestCalendar
SET WeekDay_int = WeekDay
EXEC sys.sp_spaceused @objname = N'TestCalendar', @updateusage = 'true'
ALTER TABLE [dbo].TestCalendar DROP COLUMN [WeekDay];
EXEC sp_rename 'dbo.TestCalendar.WeekDay_int', 'WeekDay', 'COLUMN';
EXEC sys.sp_spaceused @objname = N'TestCalendar', @updateusage = 'true'
DBCC SHOWCONTIG (TestCalendar) WITH ALL_INDEXES--, TABLERESULTS
DROP TABLE dbo.TestCalendar
EXECUTE sp_rename N'dbo.Tmp_TestCalendar', N'TestCalendar', 'OBJECT'
EXEC sys.sp_spaceused @objname = N'TestCalendar', @updateusage = 'true'
DBCC SHOWCONTIG (TestCalendar) WITH ALL_INDEXES--, TABLERESULTS
And here what SHOWCONTIG returns:
Initial population of TestCalendar:
DBCC SHOWCONTIG scanning 'TestCalendar' table...
Table: 'TestCalendar' (997578592); index ID: 1, database ID: 2
TABLE level scan performed.
- Pages Scanned................................: 168
- Extents Scanned..............................: 23
- Extent Switches..............................: 22
- Avg. Pages per Extent........................: 7.3
- Scan Density [Best Count:Actual Count].......: 91.30% [21:23]
- Logical Scan Fragmentation ..................: 1.79%
- Extent Scan Fragmentation ...................: 4.35%
- Avg. Bytes Free per Page.....................: 60.1
- Avg. Page Density (full).....................: 99.26%
"Sequentially" populated Tmp_TestCalendar:
DBCC SHOWCONTIG scanning 'Tmp_TestCalendar' table...
Table: 'Tmp_TestCalendar' (1061578820); index ID: 1, database ID: 2
TABLE level scan performed.
- Pages Scanned................................: 180
- Extents Scanned..............................: 27
- Extent Switches..............................: 26
- Avg. Pages per Extent........................: 6.7
- Scan Density [Best Count:Actual Count].......: 85.19% [23:27]
- Logical Scan Fragmentation ..................: 2.78%
- Extent Scan Fragmentation ...................: 11.11%
- Avg. Bytes Free per Page.....................: 40.3
- Avg. Page Density (full).....................: 99.50%
Number of pages is slightly bigger, as we replaced 2 byte smallint with 4 byte int.
Now - after altering the column in TestCalendar:
DBCC SHOWCONTIG scanning 'TestCalendar' table...
Table: 'TestCalendar' (997578592); index ID: 1, database ID: 2
TABLE level scan performed.
- Pages Scanned................................: 335
- Extents Scanned..............................: 43
- Extent Switches..............................: 334
- Avg. Pages per Extent........................: 7.8
- Scan Density [Best Count:Actual Count].......: 12.54% [42:335]
- Logical Scan Fragmentation ..................: 99.70%
- Extent Scan Fragmentation ...................: 4.65%
- Avg. Bytes Free per Page.....................: 3469.0
- Avg. Page Density (full).....................: 57.14%
As promised - number of pages doubled.
Fragmentation - through the roof.
Scan density - miserable.
Must be a lot of data manipulations done on the way, I suppose.
And we ended up with a mess in the table you have to tidy up afterwards.
Rebuilding indexes on a big table would require as much resources as the whole previous exercise.
And now - after renaming Tmp_TestCalendar to TestCalendar:
DBCC SHOWCONTIG scanning 'TestCalendar' table...
Table: 'TestCalendar' (1061578820); index ID: 1, database ID: 2
TABLE level scan performed.
- Pages Scanned................................: 180
- Extents Scanned..............................: 27
- Extent Switches..............................: 26
- Avg. Pages per Extent........................: 6.7
- Scan Density [Best Count:Actual Count].......: 85.19% [23:27]
- Logical Scan Fragmentation ..................: 2.78%
- Extent Scan Fragmentation ...................: 11.11%
- Avg. Bytes Free per Page.....................: 40.3
- Avg. Page Density (full).....................: 99.50%
Nothing's changed comparing to Tmp_TestCalendar.
Not a single byte of the data got relocated.
We've got perfectly allocated and continuous data and index pages.
Which way you'd suggest to choose for half a TB table?
_____________
Code for TallyGenerator