Hiển thị dữ liệu và phân tích sử dụng đĩa theo bảng


9

Tôi có một cơ sở dữ liệu SQL Server 2008 R2 đang được sử dụng bởi một số chương trình đã triển khai.

Câu hỏi: Có cách nào dễ dàng để hiển thị mỗi bảng tiêu tốn bao nhiêu dung lượng cho tất cả các bảng trong cơ sở dữ liệu và phân biệt không gian logic với không gian đĩa không?

Nếu tôi sử dụng SSMS (Management Studio), các thuộc tính lưu trữ được hiển thị cho cơ sở dữ liệu sẽ đọc là 167 MB với 3 MB "có sẵn" (về kích thước phù hợp, nhưng tôi lo ngại về 3 MB có sẵn - đây có phải là giới hạn đáng lo ngại không , giả sử tôi biết tôi có đủ dung lượng đĩa?)

Tôi có thể khoan vào từng bảng, nhưng phải mất mãi mãi để làm.

Tôi biết tôi có thể viết các truy vấn của riêng mình và kiểm tra xung quanh, nhưng tôi muốn biết liệu đã có cách dễ dàng (tích hợp?) Để thực hiện việc này chưa.

Câu trả lời:


13

Trong SSMS, nhấp chuột phải vào cơ sở dữ liệu và chuyển đến "Báo cáo", "Báo cáo chuẩn", "Sử dụng đĩa theo bảng". Nó sẽ cho bạn biết tổng kích thước, kích thước dữ liệu, kích thước chỉ mục và kích thước không sử dụng cho mỗi bảng (cũng như số lượng hàng).


1
Tôi đã không thấy điều đó trước đây và tôi thích nó hơn kịch bản - ngoại trừ trên một số cơ sở dữ liệu thì nó không thành công vì tôi không có quyền "XEM BẢNG TẠO NHÀ NƯỚC" - nhưng kịch bản sẽ hoạt động trong trường hợp đó. Đi đi!
Chris Woodruff

10

Nó đã được trả lời trên Stack Overflow:

SELECT 
    t.NAME AS TableName,
    s.Name AS SchemaName,
    p.rows AS RowCounts,
    SUM(a.total_pages) * 8 AS TotalSpaceKB, 
    SUM(a.used_pages) * 8 AS UsedSpaceKB, 
    (SUM(a.total_pages) - SUM(a.used_pages)) * 8 AS UnusedSpaceKB
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
LEFT OUTER JOIN 
    sys.schemas s ON t.schema_id = s.schema_id
WHERE 
    t.NAME NOT LIKE 'dt%' 
    AND t.is_ms_shipped = 0
    AND i.OBJECT_ID > 255 
GROUP BY 
    t.Name, s.Name, p.Rows
ORDER BY 
    t.Name

5

Truy vấn được liên kết đến và được sao chép bởi, @Nelson là không chính xác: nó bỏ qua Chế độ xem được lập chỉ mục, Chỉ mục toàn văn bản, Chỉ mục XML, v.v.

Nếu bạn muốn một truy vấn sẽ bao gồm mọi thứ mà không thực hiện sp_spaceusedthông qua sp_MSForEachTable, thì tôi đã đăng hai biến thể của nó (một ở đây trên DBA.StackExchange và một trên StackOverflow) vì vậy tôi sẽ không sao chép chúng ở đây:


4

Để cho vui, đây là một truy vấn sẽ tạo cùng một dữ liệu như báo cáo trong câu trả lời của nateirvin

create table #disk_usage
(
    name varchar(128)
    ,rows varchar(20)
    ,reserved varchar(20)
    ,data varchar(20)
    ,index_size varchar(20)
    ,unused varchar(20)
);

exec sp_msforeachtable 'insert into #disk_usage exec sp_spaceused [?]'

select SCHEMA_NAME(st.schema_id) + '.' + du.name 'Table Name'
 ,du.rows '# Records'
 ,du.reserved 'Reserved (KB)'
 ,du.data 'Data (KB)'
 ,du.index_size 'Indexes (KB)'
 ,du.unused 'Unused (KB)'
 from #disk_usage du
left join sys.tables st
on du.name = st.name
order by cast(left(reserved, len(reserved) - 3) as bigint) desc;

drop table #disk_usage

Được rồi, vì tôi thực sự ghét bản thân mình, tôi đã viết một truy vấn sẽ tạo ra kết quả của báo cáo, định dạng nó dưới dạng bảng HTML và gửi nó dưới dạng email. Kết hợp các màu nền báo cáo được để lại như một bài tập cho người đọc.

declare @subject nvarchar(25) = 'Disk Usage by Top Tables';

declare @recipients nvarchar(25) = 'mailbox@example.com';

create table #disk_usage
(
    name varchar(128)
    ,rows varchar(20)
    ,reserved varchar(20)
    ,data varchar(20)
    ,index_size varchar(20)
    ,unused varchar(20)
);

exec sp_msforeachtable 'insert into #disk_usage EXEC sp_spaceused [?]'

declare @body nvarchar(max) = 
'<table cellspacing="0">
    <thead>
        <tr>
            <th>Table Name</th>
            <th># Rows</th>
            <th>Reserved</th>
            <th>Data</th>
            <th>Indexes</th>
            <th>Unused</th>
        </tr>
    </thead>
';

set @body = @body + cast (
    (select '<td style="border: 1px solid black; padding: 2px">' + SCHEMA_NAME(s.schema_id) + '.' + t.name + '</td>'
     ,'<td style="border: 1px solid black; padding: 2px">' + rtrim(ltrim(t.rows)) + ' Rows </td>' -- for some reason this was generating a bunch of extra white space and I'm not going to bother to figure out why
     ,'<td style="border: 1px solid black; padding: 2px">' + t.reserved + '</td>'
     ,'<td style="border: 1px solid black; padding: 2px">' + t.data + '</td>'
     ,'<td style="border: 1px solid black; padding: 2px">' + t.index_size + '</td>'
     ,'<td style="border: 1px solid black; padding: 2px">' + t.unused + '</td>'
     from #disk_usage t
    left join sys.tables s
    on t.name = s.name
    order by cast(left(reserved, len(reserved) - 3) as bigint) desc
    for xml path ('tr'))
as nvarchar(max));

set @body = replace(replace(@body, '&lt;', '<'), '&gt;', '>')
set @body = @body + '</table>'

exec msdb.dbo.sp_send_dbmail 
@profile_name='A Database Mail Profile On The Target Server', 
@recipients=@recipients, 
@subject=@subject,
@body=@body,
@body_format='HTML'

drop table #disk_usage

1
Ồ Đó là chút cuối cùng của công việc tự ghê tởm là tuyệt vời (đối với những người khác ;-))! Cảm ơn đã thêm vào đó. Tôi rất tiếc rằng tôi có nhưng một người ủng hộ để đưa ra câu trả lời này ...
Dronz

1
:) Tôi hình dung nếu tôi phải trải qua nỗi đau khi làm điều đó, điều tối thiểu tôi có thể làm là cứu người khác khỏi cùng số phận.
MikeTheLiar
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.