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


138

ฉันจะค้นหาวัตถุที่ใหญ่ที่สุดในฐานข้อมูล SQL Server ได้อย่างไร ขั้นแรกโดยพิจารณาว่าตารางใด (และดัชนีที่เกี่ยวข้อง) มีขนาดใหญ่ที่สุดจากนั้นกำหนดว่าแถวใดในตารางใดมีขนาดใหญ่ที่สุด (เรากำลังจัดเก็บข้อมูลไบนารีใน BLOB)

มีเครื่องมือใดบ้างที่ช่วยในการวิเคราะห์ฐานข้อมูลประเภทนี้ หรือมีคำถามง่ายๆที่ฉันสามารถเรียกใช้กับตารางระบบได้หรือไม่?

คำตอบ:


290

ฉันใช้สคริปต์ SQL นี้ (ซึ่งฉันได้มาจากใครบางคน - ไม่สามารถสร้างใหม่ได้ว่าเป็นใครมาจากไหน) มานานแล้วและช่วยให้ฉันเข้าใจและกำหนดขนาดของดัชนีและตารางได้เล็กน้อย:

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) 

แน่นอนคุณสามารถใช้เกณฑ์การสั่งซื้ออื่นเช่น

ORDER BY SUM(p.rows) DESC

เพื่อรับตารางที่มีแถวมากที่สุดหรือ

ORDER BY SUM(a.total_pages) DESC

เพื่อรับตารางที่มีการใช้งานมากที่สุด (บล็อก 8K)


ยอดเยี่ยมขอบคุณ! ตอนนี้ฉันได้ จำกัด ออบเจ็กต์ที่ใหญ่ที่สุดของฉันให้แคบลงเป็นตารางที่มีข้อมูลไบนารีจำนวนมากแล้วหากต้องการทราบว่าแถวใดของข้อมูลไบนารีที่ใหญ่ที่สุด?
jamesaharvey

3
สำหรับสิ่งนั้นคุณจะต้องทำการเลือกบนตารางนั้นและพิมพ์ DATALENGTH (ฟิลด์) สำหรับแต่ละฟิลด์ที่คุณสนใจ (โดยทั่วไปคือ VARCHAR (MAX), VARBINARY (MAX) เป็นต้น
marc_s

1
ขอบคุณ @marc_s สิ่งนี้มีประโยชน์มาก คอลัมน์ TableName ยังสามารถรวมชื่อสคีมาด้วยSELECT OBJECT_SCHEMA_NAME(i.object_id) + '.' + OBJECT_NAME(i.object_id) AS TableName, ...
CruiZen

2
นั่นต้องเป็นสคริปต์ TSQL ที่สวยที่สุดเท่าที่ฉันเคยเห็นมา
Agustin Meriles

2
หากต้องการรวมดัชนีที่ไม่เป็นคลัสเตอร์ด้วยให้ลบ "และ i.index_id <= 1" ออกจากคำสั่ง WHERE
Gordon Bell

72

ใน SQL Server 2008 คุณสามารถเรียกใช้รายงานมาตรฐานการใช้งานดิสก์ตามตารางอันดับต้น ๆ สามารถพบได้โดยคลิกขวาที่ฐานข้อมูลเลือกรายงาน -> รายงานมาตรฐานแล้วเลือกรายงานที่คุณต้องการ


8
ไม่ได้ล้อเล่น? นั่นคือคำตอบที่ปฏิวัติวงการ ขอบคุณที่โพสต์ (ไม่ใช่การถากถางใช้การสืบค้นเหล่านี้ด้วยตนเองมาระยะหนึ่งแล้วและฉันไม่อยากเชื่อเลยว่าจะมีรายงานเหล่านี้อยู่แล้ว!)
Jennifer Zouak

4

แบบสอบถามนี้ช่วยในการค้นหาตารางที่ใหญ่ที่สุดในการเชื่อมต่อของคุณ

SELECT  TOP 1 OBJECT_NAME(OBJECT_ID) TableName, st.row_count
FROM sys.dm_db_partition_stats st
WHERE index_id < 2
ORDER BY st.row_count DESC

เป็นเรื่องดีที่มีบางอย่างที่เราสามารถจดจำได้ง่าย ขอบคุณสำหรับความกระชับ
David Betz

3

คุณสามารถใช้รหัสต่อไปนี้:

USE AdventureWork
GO
CREATE TABLE #GetLargest 
(
  table_name    sysname ,
  row_count     INT,
  reserved_size VARCHAR(50),
  data_size     VARCHAR(50),
  index_size    VARCHAR(50),
  unused_size   VARCHAR(50)
)

SET NOCOUNT ON

INSERT #GetLargest

EXEC sp_msforeachtable 'sp_spaceused ''?'''

SELECT 
  a.table_name,
  a.row_count,
  COUNT(*) AS col_count,
  a.data_size
  FROM #GetLargest a
     INNER JOIN information_schema.columns b
     ON a.table_name collate database_default
     = b.table_name collate database_default
       GROUP BY a.table_name, a.row_count, a.data_size
       ORDER BY CAST(REPLACE(a.data_size, ' KB', '') AS integer) DESC

DROP TABLE #GetLargest

2

หากคุณกำลังใช้ Sql Server Management Studio 2008 จะมีฟิลด์ข้อมูลบางช่องที่คุณสามารถดูได้ในหน้าต่างรายละเอียด object explorer เพียงแค่เรียกดูและเลือกโฟลเดอร์ตาราง ในมุมมองรายละเอียดคุณสามารถคลิกขวาที่ชื่อคอลัมน์และเพิ่มฟิลด์ลงใน "รายงาน" ไมล์สะสมของคุณอาจแตกต่างกันไปหากคุณใช้ SSMS 2008 express


2

ฉันพบว่าข้อความค้นหานี้มีประโยชน์มากใน SqlServerCentral นี่คือลิงก์ไปยังโพสต์ต้นฉบับ

ตารางที่ใหญ่ที่สุดของ SQL Server

  select name=object_schema_name(object_id) + '.' + object_name(object_id)
, rows=sum(case when index_id < 2 then row_count else 0 end)
, reserved_kb=8*sum(reserved_page_count)
, data_kb=8*sum( case 
     when 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 )
, index_kb=8*(sum(used_page_count) 
    - sum( case 
           when 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 )
     )    
, unused_kb=8*sum(reserved_page_count-used_page_count)
from sys.dm_db_partition_stats
where object_id > 1024
group by object_id
order by 
rows desc   

ในฐานข้อมูลของฉันพวกเขาให้ผลลัพธ์ที่แตกต่างกันระหว่างแบบสอบถามนี้และคำตอบแรก

หวังว่าใครบางคนจะพบว่ามีประโยชน์


1

คำตอบของ @ marc_s นั้นยอดเยี่ยมมากและฉันใช้มาสองสามปีแล้ว อย่างไรก็ตามฉันสังเกตเห็นว่าสคริปต์ขาดข้อมูลในดัชนีที่เก็บคอลัมน์บางตัวและไม่แสดงภาพที่สมบูรณ์ เช่นเมื่อคุณทำSUM(TotalSpace)กับสคริปต์และเปรียบเทียบกับคุณสมบัติฐานข้อมูลพื้นที่ทั้งหมดใน Management Studio ตัวเลขไม่ตรงกับในกรณีของฉัน (Management Studio แสดงตัวเลขที่ใหญ่กว่า) ฉันแก้ไขสคริปต์เพื่อเอาชนะปัญหานี้และขยายออกไปเล็กน้อย:

select
    tables.[name] as table_name,
    schemas.[name] as schema_name,
    isnull(db_name(dm_db_index_usage_stats.database_id), 'Unknown') as database_name,
    sum(allocation_units.total_pages) * 8 as total_space_kb,
    cast(round(((sum(allocation_units.total_pages) * 8) / 1024.00), 2) as numeric(36, 2)) as total_space_mb,
    sum(allocation_units.used_pages) * 8 as used_space_kb,
    cast(round(((sum(allocation_units.used_pages) * 8) / 1024.00), 2) as numeric(36, 2)) as used_space_mb,
    (sum(allocation_units.total_pages) - sum(allocation_units.used_pages)) * 8 as unused_space_kb,
    cast(round(((sum(allocation_units.total_pages) - sum(allocation_units.used_pages)) * 8) / 1024.00, 2) as numeric(36, 2)) as unused_space_mb,
    count(distinct indexes.index_id) as indexes_count,
    max(dm_db_partition_stats.row_count) as row_count,
    iif(max(isnull(user_seeks, 0)) = 0 and max(isnull(user_scans, 0)) = 0 and max(isnull(user_lookups, 0)) = 0, 1, 0) as no_reads,
    iif(max(isnull(user_updates, 0)) = 0, 1, 0) as no_writes,
    max(isnull(user_seeks, 0)) as user_seeks,
    max(isnull(user_scans, 0)) as user_scans,
    max(isnull(user_lookups, 0)) as user_lookups,
    max(isnull(user_updates, 0)) as user_updates,
    max(last_user_seek) as last_user_seek,
    max(last_user_scan) as last_user_scan,
    max(last_user_lookup) as last_user_lookup,
    max(last_user_update) as last_user_update,
    max(tables.create_date) as create_date,
    max(tables.modify_date) as modify_date
from 
    sys.tables
    left join sys.schemas on schemas.schema_id = tables.schema_id
    left join sys.indexes on tables.object_id = indexes.object_id
    left join sys.partitions on indexes.object_id = partitions.object_id and indexes.index_id = partitions.index_id
    left join sys.allocation_units on partitions.partition_id = allocation_units.container_id
    left join sys.dm_db_index_usage_stats on tables.object_id = dm_db_index_usage_stats.object_id and indexes.index_id = dm_db_index_usage_stats.index_id
    left join sys.dm_db_partition_stats on tables.object_id = dm_db_partition_stats.object_id and indexes.index_id = dm_db_partition_stats.index_id
group by schemas.[name], tables.[name], isnull(db_name(dm_db_index_usage_stats.database_id), 'Unknown')
order by 5 desc

หวังว่าจะเป็นประโยชน์สำหรับใครบางคน สคริปต์นี้ได้รับการทดสอบกับฐานข้อมูลขนาดใหญ่ทั่วทั้ง TB พร้อมด้วยตารางดัชนีและสคีมาที่แตกต่างกันหลายร้อยตาราง

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