Làm thế nào bạn có thể biết Bảng nào đang chiếm nhiều dung lượng nhất trong Cơ sở dữ liệu SQL Server 2005?


90

Làm thế nào bạn có thể biết Bảng nào đang chiếm nhiều dung lượng nhất trong Cơ sở dữ liệu SQL Server 2005?

Tôi chắc chắn có một số Quy trình lưu trữ Hệ thống hiển thị thông tin này.

Tôi có một cơ sở dữ liệu TEST đã tăng từ 1tb lên 23tb. Chúng tôi hiện đang thực hiện nhiều thử nghiệm chuyển đổi máy khách trong cơ sở dữ liệu, điều này đòi hỏi phải chạy cùng một Quy trình đã lưu chuyển đổi nhiều lần. Nó thực hiện XÓA mà tôi chắc chắn đang tăng Nhật ký giao dịch. Nhưng điều này khiến tôi phải suy nghĩ để hỏi câu hỏi này.

thông tin

vấn đề lớn là bảng dbo.Download, nó tạo ra dung lượng lớn mà thực sự không cần thiết, tôi đã có 3GB trước khi cắt bớt nó, sau đó là 52MB;)


2
Câu trả lời của Marc_S và Barry rất nổi bật nên tôi đã ủng hộ cả hai và đang chờ xem câu trả lời nào nhận được nhiều lượt bình chọn nhất để tôi có thể thưởng cho câu đó bằng "Câu trả lời được chấp nhận". Nhưng cả hai đều bị trói ở 5 vì vậy tôi chỉ chọn một nhưng tôi đã sử dụng cả hai. Cảm ơn Marc_S và Barry rất nhiều!
Gerhard Weiss

Câu trả lời:


207

Hãy thử tập lệnh này - nó sẽ liệt kê số hàng và không gian được sử dụng bởi các hàng dữ liệu (và tổng không gian được sử dụng) cho tất cả các bảng trong cơ sở dữ liệu của bạn:

SELECT 
 t.NAME AS TableName,
 i.name AS indexName,
 SUM(p.rows) AS RowCounts,
 SUM(a.total_pages) AS TotalPages, 
 SUM(a.used_pages) AS UsedPages, 
 SUM(a.data_pages) AS DataPages,
 (SUM(a.total_pages) * 8) / 1024 AS TotalSpaceMB, 
 (SUM(a.used_pages) * 8) / 1024 AS UsedSpaceMB, 
 (SUM(a.data_pages) * 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  
 i.index_id <= 1
GROUP BY 
 t.NAME, i.object_id, i.index_id, i.name 
ORDER BY 
 OBJECT_NAME(i.object_id) 

6
+1 Tuyệt vời. Lưu ý rằng điều này không bao gồm kích thước của chỉ số dữ liệu. Đối với tôi, mặc dù, nó đã hoàn thành công việc.
Erick Robertson,

39
Tôi không biết điều này, nhưng nếu bạn đang sử dụng Management Studio, bạn cũng có thể nhấp chuột phải vào cơ sở dữ liệu và đi tới Báo cáo -> Sử dụng đĩa theo bảng để có kết quả tương tự.
rossisdead

@rossisdead, đó là thông tin vui nhộn cần biết. Cảm ơn!
Nickmaovich

Tôi nhận được 'Table 'sys.tables' không tồn tại'
Seano

@Seano: bạn đang sử dụng phiên bản SQL Server nào? (chạy SELECT @@VERSIONđể tìm hiểu) Cơ sở dữ liệu của bạn có mức độ tương thích cơ sở dữ liệu nào ??
marc_s

33

Sử dụng sp_spacedUsed

Exec sp_spaceused N'YourTableName'

Hoặc nếu bạn muốn thực thi sp_spaceusedcho từng bảng trong cơ sở dữ liệu của mình thì bạn có thể sử dụng SQL này:

set nocount on
create table #spaceused (
  name nvarchar(120),
  rows char(11),
  reserved varchar(18),
  data varchar(18),
  index_size varchar(18),
  unused varchar(18)
)

declare Tables cursor for
  select name
  from sysobjects where type='U'
  order by name asc

OPEN Tables
DECLARE @table varchar(128)

FETCH NEXT FROM Tables INTO @table

WHILE @@FETCH_STATUS = 0
BEGIN
  insert into #spaceused exec sp_spaceused @table
  FETCH NEXT FROM Tables INTO @table
END

CLOSE Tables
DEALLOCATE Tables 

select * from #spaceused
drop table #spaceused

exec sp_spaceused

SQL trên là từ đây


7
Đối với các phiên bản SQL Server mới hơn, bạn cũng có thể sử dụngexec sp_msforeachtable 'exec sp_spaceused N''?'''
JNK

1
@JNK sp_msforeachtabletồn tại ít nhất là từ SQL Server 2000
SQLMenace

@SQLMenace - cảm ơn vì thông tin. Tôi đã không nghiên cứu xem nó bao nhiêu tuổi trước khi đăng, nhưng không chắc mình sẽ tìm thấy nó vì nó không có giấy tờ.
JNK

4
Một ví dụ đơn giản hơn một chút : Bạn có thể bỏ qua EXEC và trích dẫn ưa thích, bằng cách thực hiện sp_msforeachtable 'sp_spaceused [?]'nếu bạn thích. Đã xác minh trở lại SQL2000.
Đánh dấu

Đánh dấu vấn đề với phương pháp này là nó không trả lại như một tập kết quả duy nhất
Paul

7

Bình luận của Rossisdead đã trả lời câu hỏi này tốt nhất cho tôi, tôi ước gì nó không bị chôn vùi trong một bình luận. Điều này sẽ hữu ích cho những người như tôi không cố gắng tạo kịch bản cho giải pháp (OP đã không yêu cầu đoạn mã)

Nếu đang sử dụng Management Studio, bạn cũng có thể nhấp chuột phải vào cơ sở dữ liệu và đi tới Báo cáo -> Sử dụng đĩa theo bảng để có kết quả tương tự


Để nhấn mạnh: kích chuột phải vào cơ sở dữ liệu và không phải là máy chủ Instance
dhollenbeck

4

Cảm ơn @marc_s vì câu trả lời. Tôi cần biết dữ liệu so với không gian chỉ mục vì vậy tôi đã tiếp tục và mở rộng truy vấn để bao gồm điều đó.

SELECT TableName
    , SUM(DataRowCounts) AS DataRowCounts
    , SUM(DataTotalSpaceGB) AS DataTotalSpaceGB
    , SUM(DataSpaceUsedGB) AS DataSpaceUsedGB
    , SUM(DataUnusedSpaceGB) AS DataUnusedSpaceGB
    , SUM(IndexRowCounts) AS IndexRowCounts
    , SUM(IndexTotalSpaceGB) AS IndexTotalSpaceGB
    , SUM(IndexSpaceUsedGB) AS IndexSpaceUsedGB
    , SUM(IndexUnusedSpaceGB) AS IndexUnusedSpaceGB
    , SUM(DataTotalSpaceGB) + SUM(IndexTotalSpaceGB) AS TotalSpaceGB
FROM
(
SELECT t.NAME AS TableName
    , i.type_desc AS IndexType
    , CASE WHEN i.type_desc IN ('CLUSTERED', 'CLUSTERED COLUMNSTORE', 'HEAP') THEN CAST(ROUND(((SUM(a.total_pages) * 8) / 1024.00), 2)/1000 AS NUMERIC(36, 2)) ELSE 0 END AS DataTotalSpaceGB
    , CASE WHEN i.type_desc IN ('CLUSTERED', 'CLUSTERED COLUMNSTORE', 'HEAP') THEN CAST(ROUND(((SUM(a.used_pages) * 8) / 1024.00), 2)/1000 AS NUMERIC(36, 2))  ELSE 0 END AS DataSpaceUsedGB    
    , CASE WHEN i.type_desc IN ('CLUSTERED', 'CLUSTERED COLUMNSTORE', 'HEAP') THEN CAST(ROUND(((SUM(a.total_pages) - SUM(a.used_pages)) * 8) / 1024.00, 2)/1000 AS NUMERIC(36, 2)) ELSE 0 END AS DataUnusedSpaceGB
    , CASE WHEN i.type_desc IN ('CLUSTERED', 'CLUSTERED COLUMNSTORE', 'HEAP') THEN SUM(p.Rows) ELSE 0 END AS DataRowCounts
    , CASE WHEN i.type_desc = 'NONCLUSTERED' THEN CAST(ROUND(((SUM(a.total_pages) * 8) / 1024.00), 2)/1000 AS NUMERIC(36, 2)) ELSE 0 END AS IndexTotalSpaceGB
    , CASE WHEN i.type_desc = 'NONCLUSTERED' THEN CAST(ROUND(((SUM(a.used_pages) * 8) / 1024.00), 2)/1000 AS NUMERIC(36, 2))  ELSE 0 END AS IndexSpaceUsedGB    
    , CASE WHEN i.type_desc = 'NONCLUSTERED' THEN CAST(ROUND(((SUM(a.total_pages) - SUM(a.used_pages)) * 8) / 1024.00, 2)/1000 AS NUMERIC(36, 2)) ELSE 0 END AS IndexUnusedSpaceGB  
    , CASE WHEN i.type_desc = 'NONCLUSTERED' THEN SUM(p.Rows) ELSE 0 END AS IndexRowCounts
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 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
    AND s.Name = 'dbo' --update this filter
    AND t.Name = 'MyTable'
GROUP BY t.Name
    , i.type_desc
) x
GROUP BY TableName
ORDER BY TotalSpaceGB DESC
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.