如何轻松找到IDENTITY列有溢出的危险?

Kei*_*ton 5 sql-server maintenance overflow information-schema identity-column

我的数据库已经老了,我最大的一个INT IDENTITY列的价值大约是13亿.这将溢出约21亿.我计划增加它的大小,但由于数据库中的记录数量,我不想太快这样做.我可以在增加列大小之前替换我的数据库硬件,这可能会抵消这可能导致的任何性能问题.我还想关注我的数据库中超过50%已满的所有其他列.这是很多表,并且手动检查每个表是不实际的.

这就是我现在获得价值的方式(我知道返回的值可能会略微过时,但这对我的目的来说已经足够了):

PRINT IDENT_CURRENT('MyDatabase.dbo.MyTable')
Run Code Online (Sandbox Code Playgroud)

我可以用它INFORMATION_SCHEMA来获取这些信息吗?

mar*_*c_s 11

您可以查阅sys.identity_columns系统目录视图:

SELECT     
    name,
    seed_value, increment_value, last_value
FROM sys.identity_columns
Run Code Online (Sandbox Code Playgroud)

这将为您提供每列的名称,种子,增量和最后一个值.该视图还包含数据类型,因此您可以很快找出哪些标识列可能正在耗尽数字...


Kei*_*ton 5

我创建了一个存储过程来解决这个问题.它使用the INFORMATION_SCHEMA来查找IDENTITY列,然后使用IDENT_CURRENT和列DATA_TYPE来计算完整百分比.将数据库指定为第一个参数,然后选择最小百分比和数据类型.

EXEC master.dbo.CheckIdentityColumns 'MyDatabase' --all

EXEC master.dbo.CheckIdentityColumns 'MyDatabase', 50 --columns 50% full or greater

EXEC master.dbo.CheckIdentityColumns 'MyDatabase', 50, 'int' --only int columns
Run Code Online (Sandbox Code Playgroud)

示例输出:

Table                     Column             Type    Percent Full Remaining
------------------------- ------------------ ------- ------------ ---------------
MyDatabase.dbo.Table1     Table1ID           int     9            1,937,868,393
MyDatabase.dbo.Table2     Table2ID           int     5            2,019,944,894
MyDatabase.dbo.Table3     Table3ID           int     9            1,943,793,775
Run Code Online (Sandbox Code Playgroud)

我创建了一个提醒,每月检查一次我的所有数据库,然后将这些信息记录在电子表格中.

IDENTITY跟踪电子表格

CheckIdentityColumns过程

USE master
GO

CREATE PROCEDURE dbo.CheckIdentityColumns
    (
    @Database       AS NVARCHAR(128),
    @PercentFull    AS TINYINT          = 0,
    @Type           AS VARCHAR(8)       = NULL
    )

AS

--this procedure assumes you are not using negative numbers in your identity columns

DECLARE @Sql NVARCHAR(3000)

SET @Sql = 
'USE ' + @Database + '

SELECT                        
    [Column].TABLE_CATALOG + ''.'' +
    [Column].TABLE_SCHEMA + ''.'' +
    [Table].TABLE_NAME          AS [Table],
    [Column].COLUMN_NAME                        AS [Column],
    [Column].DATA_TYPE              AS [Type],
    CAST((
    CASE LOWER([Column].DATA_TYPE)
    WHEN ''tinyint''
    THEN (IDENT_CURRENT([Table].TABLE_NAME) / 255)  
    WHEN ''smallint''
    THEN (IDENT_CURRENT([Table].TABLE_NAME) / 32767)  
    WHEN ''int''
    THEN (IDENT_CURRENT([Table].TABLE_NAME) / 2147483647)  
    WHEN ''bigint''
    THEN (IDENT_CURRENT([Table].TABLE_NAME) / 9223372036854775807)  
    WHEN ''decimal''
    THEN (IDENT_CURRENT([Table].TABLE_NAME) / (([Column].NUMERIC_PRECISION * 10) - 1))  
    END * 100) AS INT)                  AS [Percent Full],
    REPLACE(CONVERT(VARCHAR(19), CAST(
    CASE LOWER([Column].DATA_TYPE)
    WHEN ''tinyint''
    THEN (255 - IDENT_CURRENT([Table].TABLE_NAME))  
    WHEN ''smallint''
    THEN (32767 - IDENT_CURRENT([Table].TABLE_NAME))  
    WHEN ''int''
    THEN (2147483647 - IDENT_CURRENT([Table].TABLE_NAME))  
    WHEN ''bigint''
    THEN (9223372036854775807 - IDENT_CURRENT([Table].TABLE_NAME))  
    WHEN ''decimal''
    THEN ((([Column].NUMERIC_PRECISION * 10) - 1) - IDENT_CURRENT([Table].TABLE_NAME))  
    END
    AS MONEY) , 1), ''.00'', '''')              AS Remaining


FROM                       
    INFORMATION_SCHEMA.COLUMNS                  AS [Column]

    INNER JOIN    
    INFORMATION_SCHEMA.TABLES                   AS [Table]
    ON      [Table].TABLE_NAME                  = [Column].TABLE_NAME

WHERE
    COLUMNPROPERTY(
        OBJECT_ID([Column].TABLE_NAME), 
        [Column].COLUMN_NAME, ''IsIdentity'') = 1 --true
    AND [Table].TABLE_TYPE                      = ''Base Table'' 
    AND [Table].TABLE_NAME                      NOT LIKE ''dt%'' 
    AND [Table].TABLE_NAME                      NOT LIKE ''MS%'' 
    AND [Table].TABLE_NAME                      NOT LIKE ''syncobj_%''
    AND CAST(
    (
    CASE LOWER([Column].DATA_TYPE)
    WHEN ''tinyint''
    THEN (IDENT_CURRENT([Table].TABLE_NAME) / 255)  
    WHEN ''smallint''
    THEN (IDENT_CURRENT([Table].TABLE_NAME) / 32767)  
    WHEN ''int''
    THEN (IDENT_CURRENT([Table].TABLE_NAME) / 2147483647)  
    WHEN ''bigint''
    THEN (IDENT_CURRENT([Table].TABLE_NAME) / 9223372036854775807)  
    WHEN ''decimal''
    THEN (IDENT_CURRENT([Table].TABLE_NAME) / (([Column].NUMERIC_PRECISION * 10) - 1))  
    END * 100
    ) AS INT)                                    >= ' + CAST(@PercentFull AS VARCHAR(4))

IF (@Type IS NOT NULL) 
    SET @Sql = @Sql + 'AND  LOWER([Column].DATA_TYPE)    = ''' + LOWER(@Type) + ''''

SET @Sql = @Sql + '

ORDER BY
    [Column].TABLE_CATALOG + ''.'' +
    [Column].TABLE_SCHEMA + ''.'' +
    [Table].TABLE_NAME,
    [Column].COLUMN_NAME'

EXECUTE sp_executesql @Sql
GO
Run Code Online (Sandbox Code Playgroud)