2011-12-19 3 views
3

Как определить пространство, используемое переменной таблицы, без использования DATALENGTH для всех столбцов?размер переменной таблицы sql без использования DATALENGTH

например:

DECLARE @T TABLE 
(
a bigint, 
b bigint, 
c int, 
d varchar(max) 
) 

insert into @T select 1,2,3, 'abc123' 

exec sp_spaceused @T 

Пытаясь определить, сколько памяти переменной Таблица потребляет при выполнении хранимой процедуры.

Я знаю, что в этом примере я могу пойти:

SELECT DATALENGTH(a) + DATALENGTH(b) + DATALENGTH(c) + DATALENGTH(d) 

Но есть ли другой способ, кроме делать DATALENGTH все столбцы таблицы?

ответ

1

Метаданные для табличных переменных практически такие же, как и для других типов таблиц, поэтому вы можете определить пространство, используемое при просмотре различных видов системы в tempdb.

Главным препятствием является то, что переменной таблицы присваивается автоматически сгенерированное имя, например #3D7E1B63, и я не уверен, есть ли прямой способ определения его object_id.

В приведенном ниже коде используется недокументированная функция %%physloc%% (требуется SQL Server 2008+) для определения страницы данных, принадлежащей переменной таблицы, а затем DBCC PAGE для получения связанного object_id. Затем он выполняет код, скопированный непосредственно из процедуры sp_spaceused, чтобы возвращать результаты.

DECLARE @T TABLE 
(
a bigint, 
b bigint, 
c int, 
d varchar(max) 
) 

insert into @T select 1,2,3, 'abc123' 
DECLARE @DynSQL nvarchar(100) 

SELECT TOP (1) @DynSQL = 'DBCC PAGE(2,' + 
         CAST(file_id AS VARCHAR) + ',' + 
         CAST(page_id AS VARCHAR) + ',1) WITH TABLERESULTS' 
FROM @T 
CROSS APPLY sys.fn_PhysLocCracker(%%physloc%%) 


DECLARE @DBCCPage TABLE (
    [ParentObject] [varchar](100) NULL, 
    [Object] [varchar](100) NULL, 
    [Field] [varchar](100) NULL, 
    [VALUE] [varchar](100) NULL 
) 
INSERT INTO @DBCCPage 
EXEC (@DynSQL) 

DECLARE @id int 

SELECT @id = VALUE 
FROM @DBCCPage 
WHERE Field = 'Metadata: ObjectId' 



EXEC sp_executesql N' 
USE tempdb 

declare @type character(2) -- The object type. 
    ,@pages bigint -- Working variable for size calc. 
    ,@dbname sysname 
    ,@dbsize bigint 
    ,@logsize bigint 
    ,@reservedpages bigint 
    ,@usedpages bigint 
    ,@rowCount bigint 
/* 
** Now calculate the summary data. 
* Note that LOB Data and Row-overflow Data are counted as Data Pages. 
*/ 
SELECT 
    @reservedpages = SUM (reserved_page_count), 
    @usedpages = SUM (used_page_count), 
    @pages = SUM ( 
    CASE 
    WHEN (index_id < 2) THEN (in_row_data_page_count + lob_used_page_count + row_overflow_used_page_count) 
    ELSE lob_used_page_count + row_overflow_used_page_count 
    END 
    ), 
    @rowCount = SUM ( 
    CASE 
    WHEN (index_id < 2) THEN row_count 
    ELSE 0 
    END 
    ) 
FROM sys.dm_db_partition_stats 
WHERE object_id = @id; 

/* 
** Check if table has XML Indexes or Fulltext Indexes which use internal tables tied to this table 
*/ 
IF (SELECT count(*) FROM sys.internal_tables WHERE parent_id = @id AND internal_type IN (202,204,211,212,213,214,215,216)) > 0 
BEGIN 
    /* 
    ** Now calculate the summary data. Row counts in these internal tables don''t 
    ** contribute towards row count of original table. 
    */ 
    SELECT 
    @reservedpages = @reservedpages + sum(reserved_page_count), 
    @usedpages = @usedpages + sum(used_page_count) 
    FROM sys.dm_db_partition_stats p, sys.internal_tables it 
    WHERE it.parent_id = @id AND it.internal_type IN (202,204,211,212,213,214,215,216) AND p.object_id = it.object_id; 
END 

SELECT 
    name = OBJECT_NAME (@id), 
    rows = convert (char(11), @rowCount), 
    reserved = LTRIM (STR (@reservedpages * 8, 15, 0) + '' KB''), 
    data = LTRIM (STR (@pages * 8, 15, 0) + '' KB''), 
    index_size = LTRIM (STR ((CASE WHEN @usedpages > @pages THEN (@usedpages - @pages) ELSE 0 END) * 8, 15, 0) + '' KB''), 
    unused = LTRIM (STR ((CASE WHEN @reservedpages > @usedpages THEN (@reservedpages - @usedpages) ELSE 0 END) * 8, 15, 0) + '' KB'') 


', N'@id int',@[email protected] 

Возвращает

name       rows  reserved   data    index_size   unused 
------------------------------ ----------- ------------------ ------------------ ------------------ ------------------ 
#451F3D2B      1   16 KB    8 KB    8 KB    0 KB 
+0

Могу ли я использовать это в SQL Server 2014/2016? Разве Microsoft не реализовала более «понятный» способ получения размера переменной таблицы? – gotqn