Como posso obter o tamanho real dos dados por linha em uma tabela do SQL Server?

33

Eu encontrei este script sql-server-2005-alcançar-tabela-linha-tamanho-limite que parece retornar o tamanho da linha por tamanhos de tipo de dados definidos. Eu preciso de um script que me dê todas as linhas em uma tabela com tamanho máximo de dados acima dos 8024 recomendados (o que a MS recomendar)

Anthony
fonte
2
Você pode tentar usar 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')e olhar para qualquer coisa onde o alloc_unit_type_descéROW_OVERFLOW_DATA
O MS SQL Server permite que apenas 8060 bytes de dados no máximo sejam armazenados em uma linha. Portanto, o tamanho da sua linha sempre será <= 8060.
AnandPhadke 5/10
2
@AnandPhadke Isso não está totalmente certo: msdn.microsoft.com/en-us/library/ms186981%28SQL.90%29.aspx
Jaime

Respostas:

44

Experimente este 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)

As linhas serão ordenadas por tamanho, para que você possa verificar de cima para baixo.

Jaime
fonte
sim a sua não se aplica para varchar I agree.Here acima de sua consulta não está cobrindo todas as colunas de uma tabela
AnandPhadke
@AnandPhadke Que colunas não estão cobrindo? Obrigado
Jaime
Por que adicionar um byte para uma coluna nula? Isso não é zero bytes? Ou é armazenado internamente como # 0?
Paul
2
@Paul, são zero bytes para colunas de comprimento variável (varchar, nvarchar ...), mas é o tamanho real do tipo de dados para colunas de comprimento fixo (int, smallint ...), então 1 é uma espécie de estimativa. NULLs são um universo inteiro :) (também há uma máscara de bitmap NULL usada para sinalizar valores NULL, que ocupa algum espaço). stackoverflow.com/questions/4546273/…
Jaime
@Paul será armazenado como zero bytes se o SQL Server estiver usando qualquer compactação de dados.
precisa saber é o seguinte
7

Gostei do exposto de Jaime. Eu adicionei alguns colchetes para lidar com nomes de colunas estranhos.

    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
fonte
3

E gostei do exposto no Speedcat e estendi-o para listar todas as tabelas com número de linhas e total de bytes.

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
fonte
0

tente isto:

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