ขนาดตารางและดัชนีใน SQL Server


91

เราสามารถมีแบบสอบถาม SQL ซึ่งโดยพื้นฐานแล้วจะช่วยในการดูตารางและขนาดดัชนีใน SQl Server

เซิร์ฟเวอร์ SQL รักษาการใช้หน่วยความจำสำหรับตาราง / ดัชนีอย่างไร


1
คุณอาจพบว่าขั้นตอนการจัดเก็บsp_helpdbมีประโยชน์
Zack Burt

1
แล้วมีคำตอบนี้ แต่ผมเองใช้แบบสอบถามในการเชื่อมโยงนี้: qualityofdata.com/2011/02/02/...
naiem

คำตอบ:


74

exec sp_spaceusedไม่มีพารามิเตอร์แสดงสรุปสำหรับฐานข้อมูลทั้งหมด โซลูชัน foreachtable จะสร้างชุดผลลัพธ์หนึ่งชุดต่อตารางซึ่ง SSMS อาจไม่สามารถจัดการได้หากคุณมีตารางมากเกินไป

ฉันสร้างสคริปต์ที่รวบรวมข้อมูลตารางผ่านsp_spaceusedและแสดงข้อมูลสรุปในชุดระเบียนเดียวโดยเรียงตามขนาด

create table #t
(
  name nvarchar(128),
  rows varchar(50),
  reserved varchar(50),
  data varchar(50),
  index_size varchar(50),
  unused varchar(50)
)

declare @id nvarchar(128)
declare c cursor for
select '[' + sc.name + '].[' + s.name + ']' FROM sysobjects s INNER JOIN sys.schemas sc ON s.uid = sc.schema_id where s.xtype='U'

open c
fetch c into @id

while @@fetch_status = 0 begin

  insert into #t
  exec sp_spaceused @id

  fetch c into @id
end

close c
deallocate c

select * from #t
order by convert(int, substring(data, 1, len(data)-3)) desc

drop table #t

4
สคริปต์ของคุณจัดการเฉพาะตารางในสคีมา 'dbo' ถ้าฉันมีตารางในฐานข้อมูลที่มีสคีมาของ 'การตรวจสอบ' sp_spaceused จะต้องถูกเรียกเช่นนี้: exec sp_spaceused 'Audit.Data' ดังนั้นจึงจำเป็นต้องแก้ไขสคริปต์เพื่อป้อนชื่อตารางที่นำหน้าด้วยชื่อสคีมา (คั่นด้วยจุด) เพื่อให้ส่งคืนข้อมูลเกี่ยวกับตารางจากสคีมาอื่น
Baodad

1
จุดดี @Boadad ... ที่ควรแก้ไขได้ง่ายสุด ๆ การแทนที่ "select name from sysobjects โดยที่ xtype = 'U'" ควรใช้เคล็ดลับ: "select '[' + sc.name + ']. [' + s.name + ']' จากระบบภายในเข้าร่วม .schemas sc ON s.uid = sc.schema_id โดยที่ s.xtype = 'U' "สคริปต์เยี่ยมมากขอบคุณ!
DCaugs

แทนที่จะใช้ตารางชั่วคราวเราสามารถแทรกข้อมูลในตารางอื่นที่ไม่ใช่ชั่วคราวได้หรือไม่?
prab2112

@PrabhakarPandey แน่นอนเพียงแค่ลบไฟล์#.
Racer SQL

120

sp_spaceused ให้ขนาดของดัชนีทั้งหมดที่รวมกัน

หากคุณต้องการขนาดของแต่ละดัชนีสำหรับตารางให้ใช้หนึ่งในสองแบบสอบถามนี้:

SELECT
    i.name                  AS IndexName,
    SUM(s.used_page_count) * 8   AS IndexSizeKB
FROM sys.dm_db_partition_stats  AS s 
JOIN sys.indexes                AS i
ON s.[object_id] = i.[object_id] AND s.index_id = i.index_id
WHERE s.[object_id] = object_id('dbo.TableName')
GROUP BY i.name
ORDER BY i.name

SELECT
    i.name              AS IndexName,
    SUM(page_count * 8) AS IndexSizeKB
FROM sys.dm_db_index_physical_stats(
    db_id(), object_id('dbo.TableName'), NULL, NULL, 'DETAILED') AS s
JOIN sys.indexes AS i
ON s.[object_id] = i.[object_id] AND s.index_id = i.index_id
GROUP BY i.name
ORDER BY i.name

ผลลัพธ์มักจะแตกต่างกันเล็กน้อย แต่ไม่เกิน 1%


ข้อความค้นหาแรกมีคีย์หลักซึ่งทำให้เกิดความสับสนเล็กน้อยด้วยเหตุผลสองประการ
quillbreaker

ข้อความค้นหาที่สองส่งมาMsg 102, Level 15, State 1, Line 5 - Incorrect syntax near '('.ที่ฉัน แต่ฉันไม่เห็นปัญหาใด ๆ กับไวยากรณ์ ความคิดใด ๆ ?
Oliver

Oliver คุณกำลังใช้งานเวอร์ชันใดอยู่ มันใช้ได้กับฉันในปี 2008R2 และ 2012
Rob Garrison

24

ใน SQL 2012 การรับข้อมูลนี้ในระดับตารางกลายเป็นเรื่องง่ายอย่างน่าอัศจรรย์:

SQL Management Studio -> คลิกขวาที่ Db -> Reports -> Standard Reports -> Disk Usage by table!

สนุก


13
EXEC sp_MSforeachtable @command1="EXEC sp_spaceused '?'"

3
หากคุณโพสต์โค้ด XML หรือตัวอย่างข้อมูลโปรดเน้นบรรทัดเหล่านั้นในโปรแกรมแก้ไขข้อความและคลิกที่ปุ่ม "ตัวอย่างโค้ด" ( { }) บนแถบเครื่องมือตัวแก้ไขเพื่อจัดรูปแบบและไวยากรณ์ให้สวยงาม
marc_s

4

คำตอบที่ประสบความสำเร็จมากที่สุดมีขนาดกะทัดรัดกว่า:

create table #tbl(
  name nvarchar(128),
  rows varchar(50),
  reserved varchar(50),
  data varchar(50),
  index_size varchar(50),
  unused varchar(50)
)

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

select * from #tbl
    order by convert(int, substring(data, 1, len(data)-3)) desc

drop table #tbl

4
--Gets the size of each index for the specified table
DECLARE @TableName sysname = N'SomeTable';

SELECT i.name AS IndexName
      ,8 * SUM(s.used_page_count) AS IndexSizeKB
FROM sys.indexes AS i
    INNER JOIN sys.dm_db_partition_stats AS s 
        ON i.[object_id] = s.[object_id] AND i.index_id = s.index_id
WHERE s.[object_id] = OBJECT_ID(@TableName, N'U')
GROUP BY i.name
ORDER BY i.name;

SELECT i.name AS IndexName
      ,8 * SUM(a.used_pages) AS IndexSizeKB
FROM sys.indexes AS i
    INNER JOIN sys.partitions AS p 
        ON i.[object_id]  = p.[object_id] AND i.index_id = p.index_id
    INNER JOIN sys.allocation_units AS a 
        ON p.partition_id = a.container_id
WHERE i.[object_id] = OBJECT_ID(@TableName, N'U')
GROUP BY i.name
ORDER BY i.name;

3

เป็นเวลานานมากแล้วที่สร้างโพสต์นี้ แต่ฉันต้องการแบ่งปันสคริปต์ของฉัน:

WITH CteIndex
AS
(
SELECT 
     reservedpages = (reserved_page_count)
     ,usedpages = (used_page_count)
     ,pages = (
            CASE
                WHEN (s.index_id < 2) THEN (in_row_data_page_count + lob_used_page_count + row_overflow_used_page_count)
                ELSE lob_used_page_count + row_overflow_used_page_count
            END
            )    
     ,s.object_id   
     ,i.index_id        
     ,i.type_desc AS IndexType
     ,i.name AS indexname
    FROM sys.dm_db_partition_stats s
    INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id] AND s.index_id = i.index_id   
)
SELECT DISTINCT
DB_NAME(DB_ID()) AS DatabaseName
,o.name AS TableName
,o.object_id
,ct.indexname
,ct.IndexType
,ct.index_id
, IndexSpace = LTRIM (STR ((CASE WHEN usedpages > pages THEN CASE WHEN ct.index_id < 2 THEN  pages ELSE (usedpages - pages) END ELSE 0 END) * 8, 15, 0) + ' KB')
FROM CteIndex ct
INNER JOIN sys.objects o ON o.object_id = ct.object_id
INNER JOIN sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL, NULL , NULL) ps ON ps.object_id = o.object_id
AND ps.index_id = ct.index_id
ORDER BY name ASC

มันใช้ได้กับ:

  • SQL Server (เริ่มตั้งแต่ปี 2008)
  • รวมข้อมูลสำหรับตารางทั้งหมดต่อฐานข้อมูลปัจจุบัน

0

มีขั้นตอนการจัดเก็บsp_spaceusedเพิ่มเติมที่ดึงข้อมูลนี้ออกมา มันค่อนข้างซับซ้อนที่จะทำจากพจนานุกรมข้อมูล แต่สิ่งนี้เชื่อมโยงแฟน ๆ ไปยังสคริปต์ที่ทำ คำถาม stackoverflow นี้มีข้อมูลเกี่ยวกับโครงสร้างข้อมูลพื้นฐานที่คุณสามารถใช้เพื่อสร้างค่าประมาณขนาดตารางและดัชนีสำหรับการวางแผน capcity


0

คำค้นหานี้มาจากคำตอบอื่นสองคำ:

รับขนาดของตารางทั้งหมดในฐานข้อมูล

จะค้นหาวัตถุที่ใหญ่ที่สุดในฐานข้อมูล SQL Server ได้อย่างไร

แต่ฉันปรับปรุงให้เป็นสากล ใช้sys.objectsพจนานุกรม:

SELECT 
    s.NAME as SCHEMA_NAME,
    t.NAME AS OBJ_NAME,
    t.type_desc as OBJ_TYPE,
    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.objects t
INNER JOIN
    sys.schemas s ON t.SCHEMA_ID = s.SCHEMA_ID 
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 
    s.NAME, t.NAME, t.type_desc, i.object_id, i.index_id, i.name 
ORDER BY
    sum(a.total_pages) DESC
;

0

หากต้องการดูข้อมูลการจัดเก็บ (และดัชนี) ของตารางเดียว:

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