如何在不使用所有列的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
尝试计算运行存储过程时Table变量消耗的内存量。
我知道在这个例子中我可以去:
SELECT DATALENGTH(a) + DATALENGTH(b) + DATALENGTH(c) + DATALENGTH(d)
但除了在所有表列上执行DATALENGTH
之外还有其他方法吗?
答案 0 :(得分: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',@id=@id
返回
name rows reserved data index_size unused
------------------------------ ----------- ------------------ ------------------ ------------------ ------------------
#451F3D2B 1 16 KB 8 KB 8 KB 0 KB