5

Moja baza danych się starzeje, a jedna z moich największych kolumn INT IDENTITY ma wartość około 1,3 miliarda. Przepełni to około 2,1 miliarda. Planuję zwiększyć jego rozmiar, ale nie chcę tego zrobić zbyt wcześnie, z powodu liczby rekordów w bazie danych. Mogę zastąpić sprzęt bazy danych przed zwiększeniem rozmiaru kolumny, co może zrekompensować wszelkie problemy z wydajnością, jakie może spowodować. Chcę również mieć na uwadze wszystkie pozostałe kolumny w moich bazach danych, które są pełne w ponad 50%. Jest wiele tabel, a sprawdzenie każdego z nich ręcznie nie jest praktyczne.Jak łatwo znaleźć kolumny IDENTITY w niebezpieczeństwie przepełnienia?

ten sposób otrzymuję wartość teraz (wiem, wartość zwracana może być nieco nieaktualne, ale jest wystarczająco dobre dla moich celów):

PRINT IDENT_CURRENT('MyDatabase.dbo.MyTable') 

Czy mogę używać INFORMATION_SCHEMA uzyskać to Informacja?

+11

[tutaj] (http://meta.stackexchange.com/questions/17463/can-i-answer-my-own-questions-even-those-where-i-knew-the-answer- przed pytaniem) i [tutaj] (http://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/) jest powodem. Zgodnie z najczęściej zadawanymi pytaniami, takie zachowanie jest nie tylko dopuszczalne, ale jest zalecane. Będę to robił, dopóki nie zostanie uznana przez społeczność SO za złą etykietę. –

+0

To nie jest odpowiedź, ale czy zacząłeś swoją tożsamość od 0 lub 1? Jeśli tak, to zamiast zwiększać rozmiar kolumny, czy rozważałeś zresetowanie tożsamości do najmniejszej int? To dałoby dodatkowe 2 miliardy z tego samego rozmiaru kolumny. –

+0

@AlexKuznetsov: Tak, rozważałem to. Mogę używać ujemnych wartości w przyszłych projektach, ale jest tak dużo kodu napisanego dla tej bazy danych, że nie chcę ryzykować jej rozbicia. –

Odpowiedz

11

można znaleźć w katalogu systemowego sys.identity_columns widok:

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

Daje to nazwę, nasion, przyrost i ostatnią wartość dla każdego kolumna. Widok zawiera również typ danych, dzięki czemu można łatwo dowiedzieć się, które kolumny tożsamości mogą być niedługo niedostępne ...

+0

Należy zauważyć, że dla widoków cross database, last_value może być nieprawidłowo zgłaszane jako null. IDENT_CURRENT (object_name (object_id)) zwróci poprawną wartość last_value. – jmoreno

5

Utworzono procedurę składowaną, aby rozwiązać ten problem. Używa ona INFORMATION_SCHEMA, aby znaleźć kolumny IDENTITY, a następnie używa IDENT_CURRENT i kolumny DATA_TYPE do obliczenia procentu pełnego. Określ bazę danych jako pierwszy parametr, a następnie opcjonalnie minimalny procent i typ danych.

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 

Przykâadowa:

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 

stworzyłem przypomnienia sprawdzenie wszystkich moich baz danych raz w miesiącu, a Loguję te informacje w arkuszu kalkulacyjnym.

IDENTITY tracking spreadsheet

CheckIdentityColumns Procedura

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 ma bardzo obszerne zapytanie, które jest bardzo dobre. Tutaj jest trochę prostsza, który opiera się na założeniu, że kolumny tożsamości są liczbami całkowitymi:

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 

Wyniki będą wyglądać następująco:

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

Checking Integer Identity Columns

0

Choć umacnianie a solution tego problem, stwierdziliśmy, że ten wątek jest zarówno interesujący, jak i interesujący (napisaliśmy również szczegółową post about this i opisaliśmy, jak działa nasze narzędzie).

W naszym rozwiązaniu przeszukujemy information_schema, aby uzyskać listę wszystkich kolumn z . Następnie napisaliśmy program, który przejdzie przez każdy z nich i obliczy maksymalne i minimalne (uwzględniamy zarówno przepełnienie, jak i niedopełnienie).

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; 
Powiązane problemy