Как я могу получить фактический размер данных на строку в таблице SQL Server?

33

Я нашел этот скрипт sql-server-2005-достигающий-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_descестьROW_OVERFLOW_DATA
Сервер MS SQL позволяет хранить максимум 8060 байт данных в строке. Поэтому ваш размер строки всегда будет <= 8060. Это никогда не будет пересекаться.
AnandPhadke
2
@AnandPhadke Это не совсем верно: msdn.microsoft.com/en-us/library/ms186981%28SQL.90%29.aspx
Jaime

Ответы:

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)

Строки будут упорядочены по размеру, так что вы можете проверить сверху вниз.

Jaime
источник
да, это не относится к varchar, я согласен. Здесь выше ваш запрос не охватывает все столбцы таблицы
AnandPhadke
@AnandPhadke Какие столбцы не покрывают? Спасибо
Хайме
Зачем добавлять один байт для нулевого столбца? Разве это не ноль байтов? Или это хранится внутри как # 0?
Пол
2
@Paul, это нулевые байты для столбцов переменной длины (varchar, nvarchar ...), но это фактическая длина типа данных для столбцов фиксированной длины (int, smallint ...), поэтому 1 является своего рода оценкой. NULL - это целая вселенная :) (есть также битовая маска NULL, используемая для пометки значений NULL, которая занимает некоторое пространство). stackoverflow.com/questions/4546273/…
Хайме
@Paul будет храниться как нулевые байты, если SQL Server использует какое-либо сжатие данных.
д.попов
7

Мне понравилось выше от Хайме. Я добавил несколько квадратных скобок для обработки странных имен столбцов.

    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
источник
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
AnandPhadke
источник