คุณจะทราบได้อย่างไรว่าตารางใดใช้พื้นที่มากที่สุดในฐานข้อมูล SQL Server 2005


91

คุณจะทราบได้อย่างไรว่าตารางใดใช้พื้นที่มากที่สุดในฐานข้อมูล SQL Server 2005

ฉันแน่ใจว่ามีขั้นตอนการจัดเก็บระบบบางอย่างที่แสดงข้อมูลนี้

ฉันมีฐานข้อมูล TEST ที่เพิ่มขึ้นจาก 1tb เป็น 23tb ขณะนี้เรากำลังทำการทดสอบการแปลงไคลเอ็นต์จำนวนมากในฐานข้อมูลซึ่งเกี่ยวข้องกับการเรียกใช้ขั้นตอนการจัดเก็บ Conversion เดียวกันหลายครั้ง มันลบซึ่งฉันแน่ใจว่ากำลังเพิ่มบันทึกธุรกรรม แต่นี่ทำให้ฉันคิดที่จะถามคำถามนี้

ข้อมูล

ปัญหาใหญ่คือตารางดาวน์โหลด dbo มันสร้างที่เก็บข้อมูลขนาดใหญ่ที่ไม่จำเป็นจริงๆฉันมี 3GB ก่อนที่จะตัดทอนมันแล้ว 52MB;)


2
คำตอบของ Marc_S และ Barry ซึ่งโดดเด่นมากดังนั้นฉันจึงโหวตให้ทั้งสองคนและรอดูว่าอันไหนได้รับการโหวตมากที่สุดฉันจะให้รางวัลกับคำตอบนั้นด้วย "คำตอบที่ยอมรับ" แต่ทั้งคู่เสมอกันที่ 5 ผมเลยเลือกมา 1 ตัว แต่ใช้ทั้งคู่ ขอบคุณ Marc_S และ Barry มาก!
Gerhard Weiss

คำตอบ:


209

ลองใช้สคริปต์นี้ - จะแสดงรายการจำนวนแถวและพื้นที่ที่ใช้โดยแถวข้อมูล (และพื้นที่ทั้งหมดที่ใช้) สำหรับตารางทั้งหมดในฐานข้อมูลของคุณ:

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 ยอดเยี่ยม โปรดทราบว่าสิ่งนี้ไม่รวมขนาดของดัชนีข้อมูล แต่สำหรับฉันมันทำให้งานเสร็จ
Erick Robertson

40
ฉันไม่ทราบสิ่งนี้ แต่ถ้าคุณใช้ Management Studio คุณสามารถคลิกขวาที่ฐานข้อมูลและไปที่รายงาน -> การใช้ดิสก์ตามตารางเพื่อให้ได้ผลลัพธ์เดียวกัน
rossisdead

@rossisdead นั่นเป็นข้อมูลที่น่ารู้ ขอบคุณ!
Nickmaovich

ฉันได้รับ 'ตาราง' sys.tables 'ไม่มีอยู่จริง'
Seano

@ Seano: คุณใช้ SQL Server เวอร์ชันอะไร (วิ่งSELECT @@VERSIONไปหา) ฐานข้อมูลของคุณมีความเข้ากันได้ในระดับใด ??
marc_s

33

ใช้sp_spacedUsed

Exec sp_spaceused N'YourTableName'

หรือถ้าคุณต้องการดำเนินการsp_spaceusedสำหรับแต่ละตารางในฐานข้อมูลของคุณคุณสามารถใช้ SQL นี้:

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 ด้านบนมาจากที่นี่


7
สำหรับ SQL Server เวอร์ชันที่ใหม่กว่าคุณสามารถใช้ได้เช่นกันexec sp_msforeachtable 'exec sp_spaceused N''?'''
JNK

1
@JNK sp_msforeachtableมีอยู่ตั้งแต่อย่างน้อย SQl Server 2000
SQLMenace

@SQLMenace - ขอบคุณสำหรับข้อมูล ฉันไม่ได้ค้นคว้าว่ามันเก่าแค่ไหนก่อนที่จะโพสต์ แต่ไม่แน่ใจว่าจะพบมันเนื่องจากไม่มีเอกสาร
JNK

4
เล็กน้อยตัวอย่างง่าย: คุณได้รับไปกับการกระโดดข้ามผู้บริหารและแฟนซี quoting โดยทำเพียงแค่sp_msforeachtable 'sp_spaceused [?]'หากคุณต้องการ ยืนยันกลับไปที่ SQL2000
ทำเครื่องหมาย

ทำเครื่องหมายปัญหาด้วยวิธีนี้คือมันไม่ได้กลับมาเป็นชุดผลลัพธ์เดียว
Paul

8

ความคิดเห็นของ Rossisdead ตอบคำถามนี้ได้ดีที่สุดสำหรับฉันฉันหวังว่ามันจะไม่ถูกฝังอยู่ในความคิดเห็น สิ่งนี้จะเป็นประโยชน์สำหรับคนอย่างฉันที่ไม่ได้พยายามเขียนสคริปต์โซลูชัน (OP ไม่ได้ขอข้อมูลโค้ด)

หากคุณใช้ Management Studio คุณสามารถคลิกขวาที่ฐานข้อมูลและไปที่รายงาน -> การใช้ดิสก์ตามตารางเพื่อให้ได้ผลลัพธ์เดียวกัน


เพื่อเน้น: คลิกขวาที่ฐานข้อมูลไม่ใช่อินสแตนซ์เซิร์ฟเวอร์
dhollenbeck

4

ขอบคุณ @marc_s สำหรับคำตอบ ฉันต้องการทราบข้อมูลเทียบกับพื้นที่ดัชนีดังนั้นฉันจึงดำเนินการต่อและขยายแบบสอบถามเพื่อรวมสิ่งนั้น

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.