Comment obtenir la taille réelle des données par ligne dans une table SQL Server?

33

J'ai trouvé ce script sql-server-2005-reach-table-row-size-limit qui semble renvoyer la taille de ligne par longueur de type de données définie. J'ai besoin d'un script qui me donnerait toutes les lignes d'une table que leur taille de données maximale est supérieure au 8024 recommandé (tout ce que MS recommande)

Anthony
la source
2
Vous pouvez essayer d'utiliser msdn.microsoft.com/en-us/library/ms188917%28v=sql.105%29.aspx - SELECT * FROM sys.dm_db_index_physical_stats(DB_ID(N'Database_Name'), OBJECT_ID(N'Table_Name'), NULL, NULL, 'DETAILED')et chercher tout ce qui se alloc_unit_type_desctrouveROW_OVERFLOW_DATA
Le serveur MS SQL n'autorise que 8060 octets de données maximum à être stockés dans une ligne.
AnandPhadke
2
@AnandPhadke Ce n'est pas tout à fait vrai: msdn.microsoft.com/en-us/library/ms186981%28SQL.90%29.aspx
Jaime

Réponses:

44

Essayez ce script:

declare @table nvarchar(128)
declare @idcol nvarchar(128)
declare @sql nvarchar(max)

--initialize those two values
set @table = 'YourTable'
set @idcol = 'some id to recognize the row'

set @sql = 'select ' + @idcol +' , (0'

select @sql = @sql + ' + isnull(datalength(' + name + '), 1)' 
        from  sys.columns 
        where object_id = object_id(@table)
        and   is_computed = 0
set @sql = @sql + ') as rowsize from ' + @table + ' order by rowsize desc'

PRINT @sql

exec (@sql)

Les rangées seront classées par taille, vous pouvez donc vérifier de haut en bas.

Jaime
la source
ouais ce n'est pas valable pour varchar je suis d'accord. Ci-dessus votre requête ne couvre pas toutes les colonnes d'une table
AnandPhadke
@AnandPhadke Quelles colonnes ne couvrent pas? Merci
Jaime
Pourquoi ajouter un octet pour une colonne nulle? N'est-ce pas zéro octet? Ou est-il stocké en interne en tant que # 0?
Paul
2
@Paul, c'est zéro octet pour les colonnes de longueur variable (varchar, nvarchar ...), mais c'est la longueur réelle du type de données pour les colonnes de longueur fixe (int, smallint ...), donc 1 est une sorte d'estimation. Les NULLs sont un Univers entier :) (il y a aussi un masque bitmap NULL utilisé pour marquer les valeurs NULL, qui prend un peu d'espace). stackoverflow.com/questions/4546273/…
Jaime
@Paul, il sera stocké sous forme de zéro octet si SQL Server utilise une compression de données.
d.popov
7

J'ai aimé ce qui précède de Jaime. J'ai ajouté des crochets pour gérer les noms de colonnes étranges.

    declare @table nvarchar(128)
    declare @idcol nvarchar(128)
    declare @sql nvarchar(max)

    --initialize those two values
    set @table = 'YourTable'
    set @idcol = 'some id to recognize the row'

    set @sql = 'select ' + @idcol +' , (0'

    select @sql = @sql + ' + isnull(datalength([' + name + ']), 1)' 
            from sys.columns where object_id = object_id(@table)
    set @sql = @sql + ') as rowsize from ' + @table + ' order by rowsize         desc'

    PRINT @sql

    exec (@sql)
Speedcat
la source
3

Et j'ai aimé ce qui précède de Speedcat et je l'ai étendu pour répertorier toutes les tables avec les nombres de lignes et le nombre total d'octets.

declare @table nvarchar(128)
declare @sql nvarchar(max)
set @sql = ''
DECLARE tableCursor CURSOR FOR  
SELECT name from sys.tables

open tableCursor
fetch next from tableCursor into @table

CREATE TABLE #TempTable( Tablename nvarchar(max), Bytes int, RowCnt int)

WHILE @@FETCH_STATUS = 0  
begin
    set @sql = 'insert into #TempTable (Tablename, Bytes, RowCnt) '
    set @sql = @sql + 'select '''+@table+''' "Table", sum(t.rowsize) "Bytes", count(*) "RowCnt" from (select (0'

    select @sql = @sql + ' + isnull(datalength([' + name + ']), 1) ' 
        from sys.columns where object_id = object_id(@table)
    set @sql = @sql + ') as rowsize from ' + @table + ' ) t '
    exec (@sql)
    FETCH NEXT FROM tableCursor INTO @table  
end

PRINT @sql

CLOSE tableCursor   
DEALLOCATE tableCursor

select * from #TempTable
select sum(bytes) "Sum" from #TempTable

DROP TABLE #TempTable
Romulus
la source
0

essaye ça:

;WITH CTE as(select *,LEN(ISNULL(col1,''))+LEN(ISNULL(col2,'')) as row_len from yourtable)
select * from CTE where row_len > 8060
AnandPhadke
la source