Skip to content

Commit 4a7afb8

Browse files
committed
sp_doc: add parameter for variable length column fill
1 parent b85e7bd commit 4a7afb8

File tree

4 files changed

+107
-32
lines changed

4 files changed

+107
-32
lines changed

docs/sp_estindex.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ how an index would look without having to actually create it!
3333
| @IsUnique | BIT | no | Whether or not the index is UNIQUE. Default is 0. |
3434
| @Filter | NVARCHAR(2048) | no | Optional filter for the index. |
3535
| @FillFactor | TINYINT | no | Optional fill factor for the index. Default is 100. |
36+
| @VarcharFillPercent | TINYINT | no | Optional estimated fill percent of data in variable length columns. Default is 100. |
3637
| @Verbose | BIT | no | Show intermediate variables used in size calculations. Default is 0. |
3738
| @SqlMajorVersion | TINYINT | no | For unit testing only. |
3839

install_dba-multitool.sql

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2292,6 +2292,12 @@ IF EXISTS (SELECT * FROM sys.fn_listextendedproperty(N'@FillFactor' , N'SCHEMA'
22922292
END;
22932293
GO
22942294

2295+
IF EXISTS (SELECT * FROM sys.fn_listextendedproperty(N'@VarcharFillPercent' , N'SCHEMA',N'dbo', N'PROCEDURE',N'sp_estindex', NULL,NULL))
2296+
BEGIN;
2297+
EXEC sys.sp_dropextendedproperty @name=N'@VarcharFillPercent' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'PROCEDURE',@level1name=N'sp_estindex';
2298+
END;
2299+
GO
2300+
22952301
IF EXISTS (SELECT * FROM sys.fn_listextendedproperty(N'@DatabaseName' , N'SCHEMA',N'dbo', N'PROCEDURE',N'sp_estindex', NULL,NULL))
22962302
BEGIN;
22972303
EXEC sys.sp_dropextendedproperty @name=N'@DatabaseName' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'PROCEDURE',@level1name=N'sp_estindex';
@@ -2322,6 +2328,7 @@ ALTER PROCEDURE [dbo].[sp_estindex]
23222328
,@IsUnique BIT = 0
23232329
,@Filter NVARCHAR(2048) = ''
23242330
,@FillFactor TINYINT = 100
2331+
,@VarcharFillPercent TINYINT = 100
23252332
,@Verbose BIT = 0
23262333
-- Unit testing only
23272334
,@SqlMajorVersion TINYINT = 0
@@ -2335,7 +2342,7 @@ sp_estindex - Estimate a new index's size and statistics.
23352342
23362343
Part of the DBA MultiTool http://dba-multitool.org
23372344
2338-
Version: 20210405
2345+
Version: 20210908
23392346
23402347
MIT License
23412348
@@ -2407,6 +2414,13 @@ BEGIN TRY
24072414
THROW 51000, @Msg, 1;
24082415
END;
24092416

2417+
/* Validate Varchar Fill Percent */
2418+
IF (@VarcharFillPercent > 100 OR @VarcharFillPercent < 1)
2419+
BEGIN;
2420+
SET @Msg = 'Varchar fill percent must be between 1 and 100.';
2421+
THROW 51000, @Msg, 1;
2422+
END;
2423+
24102424
/* Validate Filter */
24112425
IF (@Filter <> '' AND LEFT(@Filter, 5) <> 'WHERE')
24122426
BEGIN;
@@ -2596,6 +2610,7 @@ BEGIN TRY
25962610
,@NullCols INT = 0
25972611
,@IndexNullBitmap BIGINT = 0
25982612
,@VariableKeySize BIGINT = 0
2613+
,@VariableKeyFillModifier DECIMAL(3,2) = (@VarcharFillPercent / 100)
25992614
,@TotalFixedKeySize BIGINT = 0
26002615
,@IndexRowSize BIGINT = 0
26012616
,@IndexRowsPerPage BIGINT = 0
@@ -2815,23 +2830,26 @@ BEGIN TRY
28152830
END;
28162831

28172832
-- Calculate variable length data size
2818-
-- Assumes each col is 100% full
2833+
-- Assumes each col is 100% full unless
2834+
-- otherwise specified
28192835
IF (@NumVariableKeyCols > 0)
28202836
BEGIN;
2821-
SET @VariableKeySize = 2 + (@NumVariableKeyCols * 2) + @MaxVarKeySize; --The bytes added to @MaxVarKeySize are for tracking each variable column.
2837+
--The bytes added to @MaxVarKeySize are for tracking each variable column.
2838+
SET @VariableKeySize = 2 + (@NumVariableKeyCols * 2) + (@MaxVarKeySize * @VariableKeyFillModifier);
28222839
END;
28232840

28242841
-- Calculate index row size
2825-
SET @IndexRowSize = @FixedKeySize + @VariableKeySize + @IndexNullBitmap + 1 + 6; -- + 1 (for row header overhead of an index row) + 6 (for the child page ID pointer)
2826-
2842+
-- + 1 (for row header overhead of an index row) + 6 (for the child page ID pointer)
2843+
SET @IndexRowSize = @FixedKeySize + @VariableKeySize + @IndexNullBitmap + 1 + 6;
28272844
IF (@Verbose = 1)
28282845
BEGIN
28292846
SET @Msg = CONCAT('IndexRowSize: ', @IndexRowSize);
28302847
RAISERROR(@Msg, 10, 1) WITH NOWAIT;
28312848
END;
28322849

2833-
--Calculate number of index rows / page
2834-
SET @IndexRowsPerPage = FLOOR(@FreeBytesPerPage / (@IndexRowSize + 2)); -- + 2 for the row's entry in the page's slot array.
2850+
-- Calculate number of index rows / page
2851+
-- + 2 for the row's entry in the page's slot array.
2852+
SET @IndexRowsPerPage = FLOOR(@FreeBytesPerPage / (@IndexRowSize + 2));
28352853

28362854
IF (@Verbose = 1)
28372855
BEGIN
@@ -3114,6 +3132,9 @@ GO
31143132
EXEC sys.sp_addextendedproperty @name=N'Description', @value=N'Estimate a new index''s size and statistics.' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'PROCEDURE',@level1name=N'sp_estindex';
31153133
GO
31163134

3135+
EXEC sys.sp_addextendedproperty @name=N'@VarcharFillPercent', @value=N'Provide the estimated fill percent of data in variable length columns. Default is 100.' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'PROCEDURE',@level1name=N'sp_estindex';
3136+
GO
3137+
31173138
EXEC sys.sp_addextendedproperty @name=N'@Verbose', @value=N'Show intermediate variables used in size calculations. Default is 0.' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'PROCEDURE',@level1name=N'sp_estindex';
31183139
GO
31193140
SET ANSI_NULLS ON;

sp_estindex.sql

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ IF EXISTS (SELECT * FROM sys.fn_listextendedproperty(N'@FillFactor' , N'SCHEMA'
5858
END;
5959
GO
6060

61+
IF EXISTS (SELECT * FROM sys.fn_listextendedproperty(N'@VarcharFillPercent' , N'SCHEMA',N'dbo', N'PROCEDURE',N'sp_estindex', NULL,NULL))
62+
BEGIN;
63+
EXEC sys.sp_dropextendedproperty @name=N'@VarcharFillPercent' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'PROCEDURE',@level1name=N'sp_estindex';
64+
END;
65+
GO
66+
6167
IF EXISTS (SELECT * FROM sys.fn_listextendedproperty(N'@DatabaseName' , N'SCHEMA',N'dbo', N'PROCEDURE',N'sp_estindex', NULL,NULL))
6268
BEGIN;
6369
EXEC sys.sp_dropextendedproperty @name=N'@DatabaseName' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'PROCEDURE',@level1name=N'sp_estindex';
@@ -88,6 +94,7 @@ ALTER PROCEDURE [dbo].[sp_estindex]
8894
,@IsUnique BIT = 0
8995
,@Filter NVARCHAR(2048) = ''
9096
,@FillFactor TINYINT = 100
97+
,@VarcharFillPercent TINYINT = 100
9198
,@Verbose BIT = 0
9299
-- Unit testing only
93100
,@SqlMajorVersion TINYINT = 0
@@ -101,7 +108,7 @@ sp_estindex - Estimate a new index's size and statistics.
101108
102109
Part of the DBA MultiTool http://dba-multitool.org
103110
104-
Version: 20210405
111+
Version: 20210908
105112
106113
MIT License
107114
@@ -173,6 +180,13 @@ BEGIN TRY
173180
THROW 51000, @Msg, 1;
174181
END;
175182

183+
/* Validate Varchar Fill Percent */
184+
IF (@VarcharFillPercent > 100 OR @VarcharFillPercent < 1)
185+
BEGIN;
186+
SET @Msg = 'Varchar fill percent must be between 1 and 100.';
187+
THROW 51000, @Msg, 1;
188+
END;
189+
176190
/* Validate Filter */
177191
IF (@Filter <> '' AND LEFT(@Filter, 5) <> 'WHERE')
178192
BEGIN;
@@ -362,6 +376,7 @@ BEGIN TRY
362376
,@NullCols INT = 0
363377
,@IndexNullBitmap BIGINT = 0
364378
,@VariableKeySize BIGINT = 0
379+
,@VariableKeyFillModifier DECIMAL(3,2) = (@VarcharFillPercent / 100)
365380
,@TotalFixedKeySize BIGINT = 0
366381
,@IndexRowSize BIGINT = 0
367382
,@IndexRowsPerPage BIGINT = 0
@@ -581,23 +596,26 @@ BEGIN TRY
581596
END;
582597

583598
-- Calculate variable length data size
584-
-- Assumes each col is 100% full
599+
-- Assumes each col is 100% full unless
600+
-- otherwise specified
585601
IF (@NumVariableKeyCols > 0)
586602
BEGIN;
587-
SET @VariableKeySize = 2 + (@NumVariableKeyCols * 2) + @MaxVarKeySize; --The bytes added to @MaxVarKeySize are for tracking each variable column.
603+
--The bytes added to @MaxVarKeySize are for tracking each variable column.
604+
SET @VariableKeySize = 2 + (@NumVariableKeyCols * 2) + (@MaxVarKeySize * @VariableKeyFillModifier);
588605
END;
589606

590607
-- Calculate index row size
591-
SET @IndexRowSize = @FixedKeySize + @VariableKeySize + @IndexNullBitmap + 1 + 6; -- + 1 (for row header overhead of an index row) + 6 (for the child page ID pointer)
592-
608+
-- + 1 (for row header overhead of an index row) + 6 (for the child page ID pointer)
609+
SET @IndexRowSize = @FixedKeySize + @VariableKeySize + @IndexNullBitmap + 1 + 6;
593610
IF (@Verbose = 1)
594611
BEGIN
595612
SET @Msg = CONCAT('IndexRowSize: ', @IndexRowSize);
596613
RAISERROR(@Msg, 10, 1) WITH NOWAIT;
597614
END;
598615

599-
--Calculate number of index rows / page
600-
SET @IndexRowsPerPage = FLOOR(@FreeBytesPerPage / (@IndexRowSize + 2)); -- + 2 for the row's entry in the page's slot array.
616+
-- Calculate number of index rows / page
617+
-- + 2 for the row's entry in the page's slot array.
618+
SET @IndexRowsPerPage = FLOOR(@FreeBytesPerPage / (@IndexRowSize + 2));
601619

602620
IF (@Verbose = 1)
603621
BEGIN
@@ -880,5 +898,8 @@ GO
880898
EXEC sys.sp_addextendedproperty @name=N'Description', @value=N'Estimate a new index''s size and statistics.' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'PROCEDURE',@level1name=N'sp_estindex';
881899
GO
882900

901+
EXEC sys.sp_addextendedproperty @name=N'@VarcharFillPercent', @value=N'Optional estimated fill percent of data in variable length columns. Default is 100.' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'PROCEDURE',@level1name=N'sp_estindex';
902+
GO
903+
883904
EXEC sys.sp_addextendedproperty @name=N'@Verbose', @value=N'Show intermediate variables used in size calculations. Default is 0.' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'PROCEDURE',@level1name=N'sp_estindex';
884905
GO

tests/sp_estindex.Tests.sql

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ GO
120120
/*
121121
test success with included columns
122122
*/
123-
CREATE PROCEDURE [sp_estindex].[test sp succeeds with included columns]
123+
CREATE PROCEDURE [sp_estindex].[test sp succeeds on included columns]
124124
AS
125125
BEGIN;
126126

@@ -144,7 +144,7 @@ GO
144144
/*
145145
test success with unique index on heap
146146
*/
147-
CREATE PROCEDURE [sp_estindex].[test sp succeeds with unique index on heap]
147+
CREATE PROCEDURE [sp_estindex].[test sp succeeds on unique index on heap]
148148
AS
149149
BEGIN;
150150

@@ -204,7 +204,7 @@ GO
204204
/*
205205
test success with non-unique index on heap
206206
*/
207-
CREATE PROCEDURE [sp_estindex].[test sp succeeds with non-unique index on heap]
207+
CREATE PROCEDURE [sp_estindex].[test sp succeeds on non-unique index on heap]
208208
AS
209209
BEGIN;
210210

@@ -264,7 +264,7 @@ GO
264264
/*
265265
test success with unique index on clustered
266266
*/
267-
CREATE PROCEDURE [sp_estindex].[test sp succeeds with unique index on clustered]
267+
CREATE PROCEDURE [sp_estindex].[test sp succeeds on unique index on clustered]
268268
AS
269269
BEGIN;
270270

@@ -328,7 +328,7 @@ GO
328328
/*
329329
test success with multi-leaf index
330330
*/
331-
CREATE PROCEDURE [sp_estindex].[test sp succeeds with multi-leaf index]
331+
CREATE PROCEDURE [sp_estindex].[test sp succeeds on multi-leaf index]
332332
AS
333333
BEGIN;
334334

@@ -389,7 +389,7 @@ GO
389389
/*
390390
test success with non-unique index on clustered
391391
*/
392-
CREATE PROCEDURE [sp_estindex].[test sp succeeds with non-unique index on clustered]
392+
CREATE PROCEDURE [sp_estindex].[test sp succeeds on non-unique index on clustered]
393393
AS
394394
BEGIN;
395395

@@ -453,7 +453,7 @@ GO
453453
/*
454454
test success with existing ##TempMissingIndex
455455
*/
456-
CREATE PROCEDURE [sp_estindex].[test sp succeeds with existing ##TempMissingIndex]
456+
CREATE PROCEDURE [sp_estindex].[test sp succeeds on existing ##TempMissingIndex]
457457
AS
458458
BEGIN;
459459

@@ -479,7 +479,7 @@ GO
479479
/*
480480
test success with nullable columns
481481
*/
482-
CREATE PROCEDURE [sp_estindex].[test sp succeeds with nullable columns]
482+
CREATE PROCEDURE [sp_estindex].[test sp succeeds on nullable columns]
483483
AS
484484
BEGIN;
485485

@@ -501,7 +501,7 @@ GO
501501
/*
502502
test success with variable len columns
503503
*/
504-
CREATE PROCEDURE [sp_estindex].[test sp succeeds with variable len columns]
504+
CREATE PROCEDURE [sp_estindex].[test sp succeeds on variable len columns]
505505
AS
506506
BEGIN;
507507

@@ -533,7 +533,7 @@ GO
533533
/*
534534
test success with verbose mode
535535
*/
536-
CREATE PROCEDURE [sp_estindex].[test sp succeeds with verbose mode]
536+
CREATE PROCEDURE [sp_estindex].[test sp succeeds on verbose mode]
537537
AS
538538
BEGIN;
539539

@@ -555,7 +555,7 @@ GO
555555
/*
556556
test success with variable len include columns
557557
*/
558-
CREATE PROCEDURE [sp_estindex].[test sp succeeds with variable len include columns]
558+
CREATE PROCEDURE [sp_estindex].[test sp succeeds on variable len include columns]
559559
AS
560560
BEGIN;
561561

@@ -593,7 +593,7 @@ GO
593593
/*
594594
test success without @SchemaName
595595
*/
596-
CREATE PROCEDURE [sp_estindex].[test sp succeeds without @SchemaName]
596+
CREATE PROCEDURE [sp_estindex].[test sp succeeds on no @SchemaName]
597597
AS
598598
BEGIN;
599599

@@ -660,7 +660,7 @@ GO
660660
/*
661661
test failure with no @IndexColumns
662662
*/
663-
CREATE PROCEDURE [sp_estindex].[test sp fails with no @IndexColumns]
663+
CREATE PROCEDURE [sp_estindex].[test sp fails on no @IndexColumns]
664664
AS
665665
BEGIN;
666666

@@ -686,7 +686,7 @@ GO
686686
/*
687687
test failure with no @TableName
688688
*/
689-
CREATE PROCEDURE [sp_estindex].[test sp fails with no @TableName]
689+
CREATE PROCEDURE [sp_estindex].[test sp fails on no @TableName]
690690
AS
691691
BEGIN;
692692

@@ -713,7 +713,7 @@ GO
713713
/*
714714
test failure with invalid @IndexColumns
715715
*/
716-
CREATE PROCEDURE [sp_estindex].[test sp fails with invalid @IndexColumns]
716+
CREATE PROCEDURE [sp_estindex].[test sp fails on invalid @IndexColumns]
717717
AS
718718
BEGIN;
719719

@@ -745,7 +745,7 @@ GO
745745
/*
746746
test failure with invalid @Database
747747
*/
748-
CREATE PROCEDURE [sp_estindex].[test sp fails with invalid @Database]
748+
CREATE PROCEDURE [sp_estindex].[test sp fails on invalid @Database]
749749
AS
750750
BEGIN;
751751

@@ -778,7 +778,7 @@ GO
778778
/*
779779
test failure with invalid @FillFactor
780780
*/
781-
CREATE PROCEDURE [sp_estindex].[test sp fails with invalid @FillFactor]
781+
CREATE PROCEDURE [sp_estindex].[test sp fails on invalid @FillFactor]
782782
AS
783783
BEGIN;
784784

@@ -787,7 +787,6 @@ DECLARE @Verbose BIT = 0;
787787
DECLARE @IndexColumns VARCHAR(50) = 'BadColumnName';
788788
DECLARE @SchemaName SYSNAME = 'tSQLt';
789789
DECLARE @TableName SYSNAME = 'CaptureOutputLog';
790-
DECLARE @DatabaseName SYSNAME = 'IDontExist';
791790
DECLARE @FillFactor TINYINT = 101;
792791

793792
DECLARE @ExpectedMessage NVARCHAR(MAX) = '[sp_estindex]: Fill factor must be between 1 and 100.';
@@ -809,6 +808,39 @@ EXEC [dbo].[sp_estindex] @IndexColumns = @IndexColumns
809808
END;
810809
GO
811810

811+
/*
812+
test failure with invalid @VarcharFillPercent
813+
*/
814+
CREATE PROCEDURE [sp_estindex].[test sp fails on invalid @VarcharFillPercent]
815+
AS
816+
BEGIN;
817+
818+
--Build
819+
DECLARE @Verbose BIT = 0;
820+
DECLARE @IndexColumns VARCHAR(50) = 'BadColumnName';
821+
DECLARE @SchemaName SYSNAME = 'tSQLt';
822+
DECLARE @TableName SYSNAME = 'CaptureOutputLog';
823+
DECLARE @VarcharFillPercent TINYINT = 101;
824+
825+
DECLARE @ExpectedMessage NVARCHAR(MAX) = '[sp_estindex]: Varchar fill percent must be between 1 and 100.';
826+
DECLARE @ExpectedSeverity TINYINT = 16;
827+
DECLARE @ExpectedState TINYINT = 1;
828+
DECLARE @ExpectedErrorNumber INT = 50000;
829+
830+
--Assert
831+
EXEC [tSQLt].[ExpectException] @ExpectedMessage = @ExpectedMessage
832+
,@ExpectedSeverity = @ExpectedSeverity
833+
,@ExpectedState = @ExpectedState
834+
,@ExpectedErrorNumber = @ExpectedErrorNumber;
835+
EXEC [dbo].[sp_estindex] @IndexColumns = @IndexColumns
836+
,@TableName = @TableName
837+
,@SchemaName = @SchemaName
838+
,@Verbose = @Verbose
839+
,@VarcharFillPercent = @VarcharFillPercent;
840+
841+
END;
842+
GO
843+
812844
/*
813845
test failure on @Filter missing WHERE
814846
*/

0 commit comments

Comments
 (0)