如何获取SQL Server表中每行的实际数据大小?


33

我发现此脚本 sql-server-2005-reaching-table-row-size-limit 似乎返回每个定义的数据类型长度的行大小。我需要一个脚本,该脚本将为我提供表中的所有行,这些行的最大数据大小超过建议的8024(无论MS建议如何)


2
您可以尝试使用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')并寻找任何地方的alloc_unit_type_descROW_OVERFLOW_DATA

MS SQL服务器最多只能将8060字节的数据存储在一行中,因此您的行大小始终为<= 8060,它将永远不会超过此大小。
AnandPhadke,2012年

Answers:


44

试试这个脚本:

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)

这些行将按大小排序,因此您可以从上到下进行检查。


是的,它不适用于varchar我同意。在您的查询上方,该信息并未覆盖表格的所有列
AnandPhadke 2012年

@AnandPhadke哪些列未涵盖?谢谢
Jaime 2012年

为什么要为空列添加一个字节?那不是零字节吗?还是将其内部存储为#0?
保罗

2
@Paul,可变长度列(varchar,nvarchar ...)的字节为零,但是固定长度列(int,smallint ...)的数据类型的长度为实际长度,因此1是一种估计。NULL是整个Universe :)(还有一个NULL位图掩码,用于标记NULL值,这会占用一些空间)。stackoverflow.com/questions/4546273/...
海梅

@Paul,如果SQL Server使用任何数据压缩,它将存储为零字节。
d.popov '16

7

我喜欢Jaime的上述内容。我添加了一些方括号来处理奇怪的列名。

    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)

3

我喜欢Speedcat的上述内容,并将其扩展为列出具有行数和总字节数的所有表。

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

0

尝试这个:

;WITH CTE as(select *,LEN(ISNULL(col1,''))+LEN(ISNULL(col2,'')) as row_len from yourtable)
select * from CTE where row_len > 8060
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.