Pet*_*erJ 3 sql-server database-size
我有一个我继承的数据库模式,其中所有整数列都被定义为,int
但由于业务规则,许多tinyiny
数据类型可以替换为需要较少存储的其他数据类型。虽然我不期望通过使用较小的类型来提高性能,但我希望这样做的原因是:
该应用程序使用 SQL Server Express,因此我想在需要清除数据之前充分利用 10GB 的数据库大小。
该应用程序附带数据库的完整初始副本,更新使用 Microsoft 同步框架进行同步。某些客户端 PC 的 Internet 连接速度相对较慢,因此数据库大小越小越好。
我想知道是否有某种方法可以快速识别可能“超大”的列?我意识到需要仔细检查结果以确保该列永远不会超出新数据类型的限制。
以下存储过程将帮助识别这些列。它首先创建一个临时表,该表存储每个整数类型可以保存的最小值和最大值,然后运行动态查询以查找定义这些整数类型之一的每个表/列的最小值和最大值。一旦确定了最小值/最大值,它就会查找可以保存当前值的最小类型,并给出如下结果:
table_name column_name current_type min_val max_val proposed_type proposed_min proposed_max space_saved
RideLegVetting RideNumber int 1 21 tinyint 0 255 2025654
RideLegVetting LegNumber int 0 99 tinyint 0 255 2025654
Run Code Online (Sandbox Code Playgroud)
对于每一列,它显示了在表中找到的当前类型和最小/最大值,以及一个新的建议类型和它可以容纳的最小/最大值。基于基数,它还指示将节省的空间量的估计值。存储过程如下:
CREATE PROCEDURE OptimizeIntSizes AS
BEGIN
SET NOCOUNT ON
CREATE TABLE #DataTypeRanges
(
name nvarchar(128),
size tinyint,
low bigint,
high bigint
)
INSERT INTO #DataTypeRanges VALUES (N'tinyint', 1, 0, 255)
INSERT INTO #DataTypeRanges VALUES (N'smallint', 2, -32768, 32767)
INSERT INTO #DataTypeRanges VALUES (N'int', 4, -2147483648, 2147483647)
INSERT INTO #DataTypeRanges VALUES (N'bigint', 8, -9223372036854775808, 9223372036854775807)
CREATE TABLE #Results
(
table_name nvarchar(128),
column_name nvarchar(128),
current_type nvarchar(128),
min_val bigint,
max_val bigint,
proposed_type nvarchar(128),
proposed_min bigint,
proposed_max bigint,
space_saved bigint
)
DECLARE @table_name nvarchar(128)
DECLARE @column_name nvarchar(128)
DECLARE @current_type nvarchar(128)
DECLARE @proposed_type nvarchar(128)
DECLARE @low bigint
DECLARE @high bigint
DECLARE @size tinyint
DECLARE @cardinality bigint
DECLARE @min_val bigint
DECLARE @max_val bigint
DECLARE @proposed_min bigint
DECLARE @proposed_max bigint
DECLARE @proposed_size tinyint
DECLARE @space_saved bigint
DECLARE @sql nvarchar(max)
DECLARE @params nvarchar(max)
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
DECLARE FindCursor CURSOR STATIC FOR
SELECT tables.name AS table_name, cols.name AS column_name, types.name, dtr.size, dtr.low, dtr.high
FROM sys.columns cols
JOIN sys.tables tables ON tables.object_id = cols.object_id
JOIN sys.types types ON types.system_type_id = cols.system_type_id
JOIN #DataTypeRanges dtr ON dtr.name COLLATE DATABASE_DEFAULT = types.name COLLATE DATABASE_DEFAULT
OPEN FindCursor
FETCH FindCursor INTO @table_name, @column_name, @current_type, @size, @low, @high
WHILE @@FETCH_STATUS = 0
BEGIN
SET @sql = N'SELECT @cardinality_out = COUNT(1), @min_val_out = MIN([' + @column_name + ']), @max_val_out = MAX([' + @column_name + ']) FROM [' + @table_name + ']'
SET @params = N'@cardinality_out bigint OUTPUT, @min_val_out bigint OUTPUT, @max_val_out bigint OUTPUT'
EXECUTE sp_executesql @sql, @params, @cardinality_out = @cardinality OUTPUT, @min_val_out = @min_val OUTPUT, @max_val_out = @max_val OUTPUT
SELECT TOP 1 @proposed_type = name, @proposed_size = size, @proposed_min = low, @proposed_max = high
FROM #DataTypeRanges
WHERE @min_val >= low AND @max_val <= high
ORDER BY size
IF @proposed_type <> @current_type AND @max_val IS NOT NULL
BEGIN
SET @space_saved = (@size - @proposed_size) * @cardinality
INSERT INTO #Results VALUES (@table_name, @column_name, @current_type, @min_val, @max_val, @proposed_type, @proposed_min, @proposed_max, @space_saved)
END
FETCH FindCursor INTO @table_name, @column_name, @current_type, @size, @low, @high
END
CLOSE FindCursor
DEALLOCATE FindCursor
SELECT * FROM #Results ORDER BY space_saved DESC
END
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
125 次 |
最近记录: |