sử dụng không gian trên sys.allocation_units và sp_spaceuse


13

Một thực tế đã biết là DMV không lưu giữ thông tin chính xác về số lượng trang và số lượng hàng. Tuy nhiên, khi bạn có các số liệu thống kê được cập nhật, tôi không thể hiểu tại sao chúng lại không.

Tôi đang làm việc trên một công cụ giám sát, muốn biết kích thước đĩa của từng chỉ mục và dữ liệu, v.v ... Cuối cùng, tôi muốn tìm đúng hệ số lấp đầy, và những thứ khác, v.v.

Không gian được sử dụng bởi chức năng của tôi và sp_spaceuse cũ khác nhau một chút về việc sử dụng không gian, nhưng không phải là về số lượng bản ghi.

Bạn có thể thấy nếu có bất cứ điều gì thiếu trong lựa chọn của tôi?

đây là sp_spaceuse (sau đó tôi chuyển đổi các số theo 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

nhập mô tả hình ảnh ở đây

Nhưng khi tôi chạy phần chọn của mình, mã bên dưới \ hình bên dưới, tôi nhận được các số liệu hơi khác nhau.

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'

số liệu

số liệu

bức tranh lớn hơn, bao gồm các tên chỉ mục bức tranh lớn hơn, bao gồm các tên chỉ mục

Bây giờ thực hiện một số tính toán để kiểm tra kết quả:

--==================================
-- 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

nhập mô tả hình ảnh ở đây

Nó không quá xa, thực tế, ngoài thực tế tôi đã không tính toán không gian không sử dụng!

Tôi có thể làm gì để làm điều này chính xác?

SAU THAY ĐỔI:

Sau khi tôi thay thế 1024 bằng 1024.00, kết quả chính xác hơn nhiều. Tôi nhận thấy các bản ghi đã được chèn vào bảng trong câu hỏi và rõ ràng các số liệu thống kê không cập nhật, nhưng vẫn là kết quả khớp (chênh lệch dưới 1 MB - hoàn toàn phù hợp với tôi)

Các bộ kết quả mới là:

--==================================
-- 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

nhập mô tả hình ảnh ở đây

Câu trả lời:


24

Mặc dù bạn đã khắc phục sự cố làm tròn ngay lập tức, thuật toán tổng thể để lấy số liệu thống kê theo từng đối tượng / chỉ mục là không chính xác. Nó không xử lý đúng LOB và dữ liệu tràn hàng. Nó cũng loại trừ: Chế độ xem được lập chỉ mục, chỉ mục FullText, chỉ mục XML và một vài trường hợp khác. Do đó, bạn có thể không nhìn thấy tất cả dữ liệu của mình.

Sau đây là phần điều chỉnh mã tôi đã đăng lên câu trả lời trên StackOverflow ( sp_spaceuse - Cách đo kích thước tính bằng GB trong tất cả các bảng trong SQL ) xử lý tất cả các trường hợp sp_spaceusedxử lý. Câu hỏi SO đó chỉ liên quan đến thống kê theo từng đối tượng, không phải trên mỗi chỉ mục, vì vậy tôi đã điều chỉnh mã để xử lý mọi thứ ở cấp chỉ mục.

;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

Bạn đang chia INTcho nên bạn sẽ chỉ nhận được một câu trả lời toàn bộ số.

Do đó, bạn kết thúc với một vấn đề làm tròn trên các tính toán Không gian của riêng bạn. Đây là lý do tại sao, khi bạn tổng hợp chúng lại với nhau, bạn sẽ nhận được một câu trả lời khác nhau.

Mặc dù sự khác biệt là tối thiểu nhưng đây là một trong những khóa 'gotchas' với việc xử lý các số không phải là toàn bộ trong SQL Server.

Thay đổi truy vấn phân vùng của bạn trong thủ tục:

(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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.