sys.allocation_units 및 sp_spaceused의 공간 사용량


13

DMV가 페이지 수와 행 수에 대한 정확한 정보를 가지고 있지 않다는 것은 알려진 사실입니다. 그러나 통계를 업데이트하면 왜 그렇지 않은지 알 수 없습니다.

모니터링 도구를 사용하고 있으며 각 인덱스 및 데이터의 디스크 크기 등을 알고 싶습니다. 결국 올바른 채우기 비율 및 기타 사항을 찾고 싶습니다.

내 함수와 이전 sp_spaceused에서 사용하는 공간은 공간 사용량과 약간 다르지만 레코드 수는 다릅니다.

내 선택에 빠진 것이 있는지 볼 수 있습니까?

이것은 sp_spaceused입니다 (그런 다음 숫자를 MB 단위로 변환합니다) :

sp_spaceused 'tblBOrderRelationship'
go

select 318008/1024.00 AS reserved,
140208/1024.00  AS data,
177048/1024.00 AS index_size,
752/1024.00    AS unused

여기에 이미지 설명을 입력하십시오

그러나 아래의 그림 아래 코드를 선택하면 약간 다른 그림이 나타납니다.

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

SELECT 
    schema_name(t.schema_id) as SchemaName,
    t.NAME AS TableName,
    t.type_desc,
    t.is_ms_shipped,
    t.is_published,
    t.lob_data_space_id,
    t.filestream_data_space_id,
    t.is_replicated,
    t.has_replication_filter,
    t.is_merge_published,
    t.is_sync_tran_subscribed,
    --t.is_filetable,
    i.name as indexName,
    i.type_desc,
    i.is_unique,
    i.is_primary_key,
    i.is_unique_constraint,
    i.fill_factor,
    i.is_padded,


    sum(p.rows)               OVER (PARTITION BY t.OBJECT_ID,i.index_id)  as RowCounts,
    sum(a.total_pages)        OVER (PARTITION BY t.OBJECT_ID,i.index_id)  as TotalPages, 
    sum(a.used_pages)         OVER (PARTITION BY t.OBJECT_ID,i.index_id)  as UsedPages, 
    sum(a.data_pages)         OVER (PARTITION BY t.OBJECT_ID,i.index_id)  as DataPages,

    (sum(a.total_pages)       OVER (PARTITION BY t.OBJECT_ID,i.index_id)  * 8) / 1024 as TotalSpaceMB, 
    (sum(a.used_pages)        OVER (PARTITION BY t.OBJECT_ID,i.index_id)  * 8) / 1024 as UsedSpaceMB, 
    (sum(a.data_pages)        OVER (PARTITION BY t.OBJECT_ID,i.index_id)  * 8) / 1024 as DataSpaceMB
FROM 
    sys.tables t
INNER JOIN      
    sys.indexes i ON t.OBJECT_ID = i.object_id
INNER JOIN 
    sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
INNER JOIN 
    sys.allocation_units a ON p.partition_id = a.container_id
WHERE 
    t.NAME NOT LIKE 'dt%' AND
    i.OBJECT_ID > 255 
AND T.NAME = 'tblBOrderRelationship'

인물

인물

색인 이름을 포함한 더 큰 그림 색인 이름을 포함한 더 큰 그림

이제 계산을 수행하여 결과를 확인하십시오.

--==================================
-- the figures from sp_spaceused
--==================================
select 318008/1024.00 AS reserved,
140208/1024.00  AS data,
177048/1024.00 AS index_size,
752/1024.00    AS unused

--==================================
-- the figures from my select
--==================================
select 137+61+56+54 AS reserved,
       137 AS data,
       61+56+54 AS index_size

여기에 이미지 설명을 입력하십시오

사용하지 않은 공간을 계산하지 않았다는 사실을 제외하면 실제로 그렇게 멀지 않습니다!

이것을 정확하게하려면 어떻게해야합니까?

변경 후 :

1024를 1024.00으로 바꾸면 결과가 훨씬 정확합니다. 문제의 테이블에 레코드가 삽입 된 것을 발견했으며 통계는 최신이 아니지만 결과는 여전히 일치합니다 (1MB 미만-나에게 적합합니다).

새로운 결과 집합은 다음과 같습니다.

--==================================
-- the figures from sp_spaceused
--==================================
select
318072 /1024.00 AS reserved,
140208 /1024.00 AS data,
177096 /1024.00 AS index_size,
768 /1024.00 AS unused
go

--==================================
-- the figures from my select
--==================================
select 137.7578125+61.7968750+56.4218750+54.6406250 as reserved,
       137.7578125 as data,
       61.7968750+56.4218750+54.6406250 as index_size

여기에 이미지 설명을 입력하십시오

답변:


24

즉각적인 반올림 문제를 해결했지만 개체 별 / 인덱스 통계를 얻는 전체 알고리즘이 잘못되었습니다. LOB 및 행 오버 플로우 데이터를 올바르게 처리하지 않습니다. 인덱싱 된 뷰, 전체 텍스트 인덱스, XML 인덱스 및 기타 몇 가지 경우도 제외됩니다. 따라서 일부 데이터가 표시되지 않을 수 있습니다.

다음은 처리하는 모든 사례를 처리 하는 StackOverflow ( sp_spaceused-SQL의 모든 테이블에서 크기를 GB로 측정하는 방법) 에 대한 답변에 게시 한 코드의 적응입니다 sp_spaceused. 이 SO 질문은 인덱스가 아닌 객체 별 통계에만 관심이 있으므로 인덱스 수준에서 일을 처리하도록 코드를 조정했습니다.

;WITH agg AS
(   -- Get info for Tables, Indexed Views, etc
    SELECT  ps.[object_id] AS [ObjectID],
            ps.index_id AS [IndexID],
            NULL AS [ParentIndexID],
            NULL AS [PassThroughIndexName],
            NULL AS [PassThroughIndexType],
            SUM(ps.in_row_data_page_count) AS [InRowDataPageCount],
            SUM(ps.used_page_count) AS [UsedPageCount],
            SUM(ps.reserved_page_count) AS [ReservedPageCount],
            SUM(ps.row_count) AS [RowCount],
            SUM(ps.lob_used_page_count + ps.row_overflow_used_page_count)
                    AS [LobAndRowOverflowUsedPageCount]
    FROM    sys.dm_db_partition_stats ps
    GROUP BY    ps.[object_id],
                ps.[index_id]
    UNION ALL
    -- Get info for FullText indexes, XML indexes, Spatial indexes, etc
    SELECT  sit.[parent_id] AS [ObjectID],
            sit.[object_id] AS [IndexID],
            sit.[parent_minor_id] AS [ParentIndexID],
            sit.[name] AS [PassThroughIndexName],
            sit.[internal_type_desc] AS [PassThroughIndexType],
            0 AS [InRowDataPageCount],
            SUM(ps.used_page_count) AS [UsedPageCount],
            SUM(ps.reserved_page_count) AS [ReservedPageCount],
            0 AS [RowCount],
            0 AS [LobAndRowOverflowUsedPageCount]
    FROM    sys.dm_db_partition_stats ps
    INNER JOIN  sys.internal_tables sit
            ON  sit.[object_id] = ps.[object_id]
    WHERE   sit.internal_type IN
               (202, 204, 207, 211, 212, 213, 214, 215, 216, 221, 222, 236)
    GROUP BY    sit.[parent_id],
                sit.[object_id],
                sit.[parent_minor_id],
                sit.[name],
                sit.[internal_type_desc]
), spaceused AS
(
SELECT  agg.[ObjectID],
        agg.[IndexID],
        agg.[ParentIndexID],
        agg.[PassThroughIndexName],
        agg.[PassThroughIndexType],
        OBJECT_SCHEMA_NAME(agg.[ObjectID]) AS [SchemaName],
        OBJECT_NAME(agg.[ObjectID]) AS [TableName],
        SUM(CASE
                WHEN (agg.IndexID < 2) THEN agg.[RowCount]
                ELSE 0
            END) AS [Rows],
        SUM(agg.ReservedPageCount) * 8 AS [ReservedKB],
        SUM(agg.LobAndRowOverflowUsedPageCount +
            CASE
                WHEN (agg.IndexID < 2) THEN (agg.InRowDataPageCount)
                ELSE 0
            END) * 8 AS [DataKB],
        SUM(agg.UsedPageCount - agg.LobAndRowOverflowUsedPageCount -
            CASE
                WHEN (agg.IndexID < 2) THEN agg.InRowDataPageCount
                ELSE 0
            END) * 8 AS [IndexKB],
        SUM(agg.ReservedPageCount - agg.UsedPageCount) * 8 AS [UnusedKB],
        SUM(agg.UsedPageCount) * 8 AS [UsedKB]
FROM    agg
GROUP BY    agg.[ObjectID],
            agg.[IndexID],
            agg.[ParentIndexID],
            agg.[PassThroughIndexName],
            agg.[PassThroughIndexType],
            OBJECT_SCHEMA_NAME(agg.[ObjectID]),
            OBJECT_NAME(agg.[ObjectID])
)
SELECT sp.SchemaName,
       sp.TableName,
       sp.IndexID,
       CASE
         WHEN (sp.IndexID > 0) THEN COALESCE(si.[name], sp.[PassThroughIndexName])
         ELSE N'<Heap>'
       END AS [IndexName],
       sp.[PassThroughIndexName] AS [InternalTableName],
       sp.[Rows],
       sp.ReservedKB,
       (sp.ReservedKB / 1024.0 / 1024.0) AS [ReservedGB],
       sp.DataKB,
       (sp.DataKB / 1024.0 / 1024.0) AS [DataGB],
       sp.IndexKB,
       (sp.IndexKB / 1024.0 / 1024.0) AS [IndexGB],
       sp.UsedKB AS [UsedKB],
       (sp.UsedKB / 1024.0 / 1024.0) AS [UsedGB],
       sp.UnusedKB,
       (sp.UnusedKB / 1024.0 / 1024.0) AS [UnusedGB],
       so.[type_desc] AS [ObjectType],
       COALESCE(si.type_desc, sp.[PassThroughIndexType]) AS [IndexPrimaryType],
       sp.[PassThroughIndexType] AS [IndexSecondaryType],
       SCHEMA_ID(sp.[SchemaName]) AS [SchemaID],
       sp.ObjectID
       --,sp.ParentIndexID
FROM   spaceused sp
INNER JOIN sys.all_objects so -- in case "WHERE so.is_ms_shipped = 0" is removed
        ON so.[object_id] = sp.ObjectID
LEFT JOIN  sys.indexes si
       ON  si.[object_id] = sp.ObjectID
      AND  (si.[index_id] = sp.IndexID
         OR si.[index_id] = sp.[ParentIndexID])
WHERE so.is_ms_shipped = 0
--so.[name] LIKE N''  -- optional name filter
--ORDER BY ????

8

당신은 나누기 INT때문에 정수 답변 만받을 수 있습니다.

따라서 공간 계산에서 반올림 문제가 발생합니다. 그렇기 때문에 함께 합하면 다른 대답을 얻을 수 있습니다.

차이는 최소이지만 SQL Server에서 전체가 아닌 숫자를 처리하는 데있어 중요한 '중고차'중 하나입니다.

절차에서 파티션 쿼리를 변경하십시오.

(sum(a.total_pages)       OVER (PARTITION BY t.OBJECT_ID,i.index_id)  * 8) / 1024.00 as TotalSpaceMB, 
(sum(a.used_pages)        OVER (PARTITION BY t.OBJECT_ID,i.index_id)  * 8) / 1024.00 as UsedSpaceMB, 
(sum(a.data_pages)        OVER (PARTITION BY t.OBJECT_ID,i.index_id)  * 8) / 1024.00 as DataSpaceMB
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.