2011-12-19 7 views
3

모든 열에서 DATALENGTH을 사용하지 않고 테이블 변수가 사용하는 공간을 어떻게 결정합니까?DATALENGTH를 사용하지 않는 SQL 테이블 변수의 크기

예 : 저장 프로 시저를 실행하는 경우 테이블 변수가 소비하는 메모리 양을 해결하려고 노력

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을 직접 확인할 방법이 있는지 확실하지 않습니다.

아래 코드는 DBCC PAGE 테이블 변수에 속한 데이터 페이지를 확인하여 연결된 object_id을 얻으려면 문서화되지 않은 %%physloc%% 함수 (SQL Server 2008 이상 필요)를 사용합니다. 그런 다음 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 서버 2,016분의 2,014이 사용할 수 있습니까? Microsoft가 테이블 변수의 크기를 가져 오는 데 '명확한'방법을 구현하지 않았습니까? – gotqn