Jak mogę uzyskać rzeczywisty rozmiar danych dla wiersza w tabeli programu SQL Server?

33

Znalazłem ten skrypt sql-server-2005-reach-table-table-row-size-limit, który wydaje się zwracać rozmiar wiersza dla zdefiniowanych długości typów danych. Potrzebuję skryptu, który dałby mi wszystkie wiersze w tabeli, że ich maksymalny rozmiar danych jest większy niż zalecany 8024 (cokolwiek zaleca MS)

Anthony
źródło
2
Możesz spróbować użyć 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')i poszukać czegokolwiek, gdzie alloc_unit_type_descjestROW_OVERFLOW_DATA
Serwer MS SQL zezwala na przechowywanie maksymalnie 8060 bajtów danych w jednym rzędzie, dlatego rozmiar wiersza będzie zawsze wynosił <= 8060 i nigdy go nie przekroczy.
AnandPhadke
2
@AnandPhadke To nie do końca prawda: msdn.microsoft.com/en-us/library/ms186981%28SQL.90%29.aspx
Jaime,

Odpowiedzi:

44

Wypróbuj ten skrypt:

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)

Wiersze zostaną uporządkowane według rozmiaru, dzięki czemu można sprawdzać od góry do dołu.

Jaime
źródło
tak, to nie dotyczy varchar Zgadzam się. Powyżej twoje zapytanie nie obejmuje wszystkich kolumn tabeli
AnandPhadke
@AnandPhadke Jakie kolumny nie obejmują? Dzięki
Jaime,
Po co dodawać jeden bajt dla pustej kolumny? Czy to nie jest zero bajtów? Czy jest przechowywany wewnętrznie jako numer 0?
Paul
2
@Paul, to zero bajtów dla kolumn o zmiennej długości (varchar, nvarchar ...), ale jest to rzeczywista długość typu danych dla kolumn o stałej długości (int, smallint ...), więc 1 jest rodzajem szacunku. Wartości NULL to cały Wszechświat :) (istnieje również maska ​​bitmapowa NULL używana do oznaczania wartości NULL, która zajmuje trochę miejsca). stackoverflow.com/questions/4546273/…
Jaime
@Paul będzie przechowywany jako zero bajtów, jeśli SQL Server używa dowolnej kompresji danych.
d.popov
7

Podobało mi się powyższe od Jaime. Dodałem kilka nawiasów kwadratowych do obsługi dziwnych nazw kolumn.

    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
źródło
3

I podobało mi się powyższe z Speedcat i rozszerzyłem go, aby wyświetlić wszystkie tabele z liczbą wierszy i całkowitą liczbą bajtów.

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
źródło
0

Spróbuj tego:

;WITH CTE as(select *,LEN(ISNULL(col1,''))+LEN(ISNULL(col2,'')) as row_len from yourtable)
select * from CTE where row_len > 8060
AnandPhadke
źródło