5

Cơ sở dữ liệu của tôi đang cũ, và một trong các cột INT IDENTITY lớn nhất của tôi có giá trị khoảng 1,3 tỷ. Điều này sẽ tràn khoảng 2,1 tỷ đồng. Tôi có kế hoạch tăng kích thước của nó, nhưng tôi không muốn làm điều đó quá sớm vì số lượng hồ sơ trong cơ sở dữ liệu. Tôi có thể thay thế phần cứng cơ sở dữ liệu của mình trước khi tôi tăng kích thước cột, có thể bù đắp bất kỳ vấn đề hiệu năng nào mà điều này có thể gây ra. Tôi cũng muốn giữ một mắt trên tất cả các cột khác trong cơ sở dữ liệu của tôi có hơn 50% đầy đủ. Đó là rất nhiều bảng, và kiểm tra từng người một cách thủ công là không thực tế.Làm cách nào để dễ dàng tìm thấy các cột IDENTITY có nguy cơ bị tràn?

Đây là cách tôi nhận được giá trị bây giờ (tôi biết giá trị trả về có thể hơi trong ngày, nhưng nó đủ tốt cho mục đích của tôi):

PRINT IDENT_CURRENT('MyDatabase.dbo.MyTable') 

Tôi có thể sử dụng INFORMATION_SCHEMA để có được điều này thông tin?

+11

[Ở đây] (http://meta.stackexchange.com/questions/17463/can-i-answer-my-own-questions-even-those-where-i-knew-the-answer- trước khi yêu cầu) và [ở đây] (http://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/) là lý do tại sao. Theo SO Hỏi đáp, hành vi này không chỉ chấp nhận được, nhưng nó được khuyến khích. Tôi sẽ tiếp tục làm điều đó cho đến khi nó được coi là nghi thức xấu bởi cộng đồng SO. –

+0

Đây không phải là câu trả lời, nhưng bạn đã bắt đầu nhận dạng của mình từ 0 hay 1 chưa? Nếu có, thì thay vì tăng kích thước cột, bạn có xem xét đặt lại danh tính thành int nhỏ nhất không? Điều đó sẽ cung cấp cho bạn thêm 2 tỷ trong cùng một kích thước cột. –

+0

@AlexKuznetsov: Vâng, tôi đã cân nhắc điều đó. Tôi có thể sử dụng các giá trị âm trong các dự án tương lai, nhưng có quá nhiều mã được viết cho cơ sở dữ liệu này mà tôi không muốn mạo hiểm phá vỡ nó. –

Trả lời

11

Bạn có thể tham khảo các cửa hàng sys.identity_columns hệ thống xem:

SELECT  
    name, 
    seed_value, increment_value, last_value 
FROM sys.identity_columns 

này cung cấp cho bạn tên, hạt giống, tăng và giá trị cuối cùng cho mỗi cột. Chế độ xem cũng chứa loại dữ liệu, vì vậy bạn có thể dễ dàng tìm ra các cột nhận dạng nào có thể sắp hết số ...

+0

Lưu ý rằng đối với chế độ xem cơ sở dữ liệu chéo, last_value có thể được báo cáo không chính xác là null. IDENT_CURRENT (object_name (object_id)) sẽ trả về giá trị last_value chính xác. – jmoreno

5

Tôi đã tạo một quy trình được lưu trữ để giải quyết vấn đề này. Nó sử dụng INFORMATION_SCHEMA để tìm các cột IDENTITY và sau đó sử dụng IDENT_CURRENT và cột của DATA_TYPE để tính phần trăm đầy đủ. Chỉ định cơ sở dữ liệu làm tham số đầu tiên, và sau đó tùy chọn phần trăm tối thiểu và kiểu dữ liệu.

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 

Ví dụ đầu ra:

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 

Tôi tạo ra một lời nhắc nhở để kiểm tra tất cả các cơ sở dữ liệu của tôi một lần mỗi tháng, và tôi đăng thông tin này trong một bảng tính.

IDENTITY tracking spreadsheet

CheckIdentityColumns Thủ tục

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 
2

Keith Walton có một truy vấn rất toàn diện rất tốt. Dưới đây là một chút một đơn giản hơn đó là dựa trên giả định rằng các cột sắc là tất cả các số nguyên:

SELECT sys.tables.name AS [Table Name], 
    last_value AS [Last Value],  
    MAX_LENGTH, 
    CAST(cast(last_value as int)/2147483647.0 * 100.0 AS DECIMAL(5,2)) 
     AS [Percentage of ID's Used], 
    2147483647 - cast(last_value as int) AS Remaining 
FROM sys.identity_columns 
    INNER JOIN sys.tables 
     ON sys.identity_columns.object_id = sys.tables.object_id 
ORDER BY last_value DESC 

Kết quả sẽ giống như thế này:

Table Name  Last Value  MAX_LENGTH Percentage of ID's Used Remaining 
My_Table  49181800    4    2.29    2098301847 

Checking Integer Identity Columns

0

Trong khi crafting a solution cho điều này vấn đề, chúng tôi tìm thấy chủ đề này cả thông tin và thú vị (chúng tôi cũng đã viết chi tiết post about this và mô tả cách thức hoạt động của công cụ của chúng tôi).

Trong giải pháp của chúng tôi, chúng tôi đang truy vấn information_schema để có được danh sách tất cả các cột. Sau đó, chúng tôi đã viết một chương trình mà sẽ đi qua mỗi người trong số họ và tính toán tối đa và tối thiểu (chúng tôi tài khoản cho cả tràn và tràn).

SELECT 
    b.COLUMN_NAME, 
    b.COLUMN_TYPE, 
    b.DATA_TYPE, 
    b.signed, 
    a.TABLE_NAME, 
    a.TABLE_SCHEMA 
FROM (
    -- get all tables 
    SELECT 
    TABLE_NAME, TABLE_SCHEMA 
    FROM information_schema.tables 
    WHERE 
    TABLE_TYPE IN ('BASE TABLE', 'VIEW') AND 
    TABLE_SCHEMA NOT IN ('mysql', 'performance_schema') 
) a 
JOIN (
    -- get information about columns types 
    SELECT 
    TABLE_NAME, 
    COLUMN_NAME, 
    COLUMN_TYPE, 
    TABLE_SCHEMA, 
    DATA_TYPE, 
    (!(LOWER(COLUMN_TYPE) REGEXP '.*unsigned.*')) AS signed 
    FROM information_schema.columns 
) b ON a.TABLE_NAME = b.TABLE_NAME AND a.TABLE_SCHEMA = b.TABLE_SCHEMA 
ORDER BY a.TABLE_SCHEMA DESC; 
Các vấn đề liên quan