ฉันได้รับมรดกฐานข้อมูล SQL Server ที่ค่อนข้างใหญ่ ดูเหมือนว่าจะใช้พื้นที่มากเกินกว่าที่ฉันคาดไว้เนื่องจากข้อมูลมีอยู่
มีวิธีง่าย ๆ ในการกำหนดเนื้อที่บนดิสก์ในแต่ละตารางที่ใช้ไปหรือไม่
ฉันได้รับมรดกฐานข้อมูล SQL Server ที่ค่อนข้างใหญ่ ดูเหมือนว่าจะใช้พื้นที่มากเกินกว่าที่ฉันคาดไว้เนื่องจากข้อมูลมีอยู่
มีวิธีง่าย ๆ ในการกำหนดเนื้อที่บนดิสก์ในแต่ละตารางที่ใช้ไปหรือไม่
คำตอบ:
SELECT
t.NAME AS TableName,
s.Name AS SchemaName,
p.rows,
SUM(a.total_pages) * 8 AS TotalSpaceKB,
CAST(ROUND(((SUM(a.total_pages) * 8) / 1024.00), 2) AS NUMERIC(36, 2)) AS TotalSpaceMB,
SUM(a.used_pages) * 8 AS UsedSpaceKB,
CAST(ROUND(((SUM(a.used_pages) * 8) / 1024.00), 2) AS NUMERIC(36, 2)) AS UsedSpaceMB,
(SUM(a.total_pages) - SUM(a.used_pages)) * 8 AS UnusedSpaceKB,
CAST(ROUND(((SUM(a.total_pages) - SUM(a.used_pages)) * 8) / 1024.00, 2) AS NUMERIC(36, 2)) AS UnusedSpaceMB
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
TotalSpaceMB DESC, t.Name
หากคุณใช้SQL Server Management Studio (SSMS) แทนที่จะเรียกใช้แบบสอบถาม ( ซึ่งในกรณีของฉันส่งคืนแถวที่ซ้ำกัน ) คุณสามารถเรียกใช้รายงานมาตรฐานได้
หมายเหตุ: ระดับความเข้ากันได้ของฐานข้อมูลต้องถูกตั้งค่าเป็น 90 หรือสูงกว่าเพื่อให้สิ่งนี้ทำงานได้อย่างถูกต้อง ดูhttp://msdn.microsoft.com/en-gb/library/bb510680.aspx
sp_spaceused สามารถรับข้อมูลเกี่ยวกับพื้นที่ดิสก์ที่ใช้โดยตารางมุมมองที่จัดทำดัชนีหรือฐานข้อมูลทั้งหมด
ตัวอย่างเช่น:
USE MyDatabase; GO
EXEC sp_spaceused N'User.ContactInfo'; GO
สิ่งนี้รายงานข้อมูลการใช้ดิสก์สำหรับตาราง ContactInfo
วิธีใช้สำหรับตารางทั้งหมดในครั้งเดียว:
USE MyDatabase; GO
sp_msforeachtable 'EXEC sp_spaceused [?]' GO
นอกจากนี้คุณยังสามารถใช้งานดิสก์ได้จากภายในคลิกขวาที่ฟังก์ชั่นรายงานมาตรฐานของ SQL Server เมื่อต้องการไปที่รายงานนี้ให้นำทางจากวัตถุเซิร์ฟเวอร์ใน Object Explorer เลื่อนลงไปที่วัตถุฐานข้อมูลแล้วคลิกขวาที่ฐานข้อมูลใด ๆ จากเมนูที่ปรากฏขึ้นให้เลือกรายงานจากนั้นรายงานมาตรฐานจากนั้นเลือก "การใช้ดิสก์ตามพาร์ทิชัน: [ชื่อฐานข้อมูล]"
sp_msforeachtable
ใน SSMS อาจก่อให้เกิด a System.OutOfMemoryException
หากคุณมีตารางจำนวนมากดังนั้นจึงควรใช้ตารางชั่วคราวเพื่อเก็บผลลัพธ์
นี่คือวิธีอื่น: การใช้SQL Server Management StudioในObject Explorerไปที่ฐานข้อมูลของคุณและเลือกตาราง
จากนั้นเปิดรายละเอียด Object Explorer (โดยการกดF7หรือไปที่View-> Object Explorer Details ) ในหน้ารายละเอียดนักสำรวจวัตถุคลิกขวาที่ส่วนหัวคอลัมน์และเปิดใช้งานคอลัมน์ที่คุณต้องการดูในหน้า คุณสามารถเรียงลำดับข้อมูลตามคอลัมน์ใดก็ได้เช่นกัน
หลังจากการค้นหาบางอย่างฉันไม่สามารถหาวิธีที่ง่ายในการรับข้อมูลในทุกตาราง มีโพรซีเดอร์ที่เก็บสะดวกที่ชื่อ sp_spaceused ซึ่งจะส่งคืนพื้นที่ทั้งหมดที่ใช้โดยฐานข้อมูล หากให้มาพร้อมกับชื่อตารางมันจะคืนค่าพื้นที่ที่ใช้โดยตารางนั้น อย่างไรก็ตามผลลัพธ์ที่ส่งคืนโดยกระบวนงานที่เก็บไว้จะไม่สามารถจัดเรียงได้เนื่องจากคอลัมน์เป็นค่าอักขระ
สคริปต์ต่อไปนี้จะสร้างข้อมูลที่ฉันกำลังมองหา
create table #TableSize (
Name varchar(255),
[rows] int,
reserved varchar(255),
data varchar(255),
index_size varchar(255),
unused varchar(255))
create table #ConvertedSizes (
Name varchar(255),
[rows] int,
reservedKb int,
dataKb int,
reservedIndexSize int,
reservedUnused int)
EXEC sp_MSforeachtable @command1="insert into #TableSize
EXEC sp_spaceused '?'"
insert into #ConvertedSizes (Name, [rows], reservedKb, dataKb, reservedIndexSize, reservedUnused)
select name, [rows],
SUBSTRING(reserved, 0, LEN(reserved)-2),
SUBSTRING(data, 0, LEN(data)-2),
SUBSTRING(index_size, 0, LEN(index_size)-2),
SUBSTRING(unused, 0, LEN(unused)-2)
from #TableSize
select * from #ConvertedSizes
order by reservedKb desc
drop table #TableSize
drop table #ConvertedSizes
exec sp_spaceused N'dbo.MyTable'
สำหรับตารางทั้งหมดใช้ .. (เพิ่มจากความคิดเห็นของ Paul)
exec sp_MSForEachTable 'exec sp_spaceused [?]'
exec sp_helpdb
ที่ไม่แสดงอะไรเกี่ยวกับตารางexec sp_spaceused
ที่จะ - แต่เพียงครั้งละหนึ่งตาราง ... มันไม่ได้ให้ภาพรวมของสิ่งที่คุณมีตารางและจำนวนแถวที่พวกเขามีและวิธี พวกเขาใช้พื้นที่มาก
ข้อความค้นหาด้านบนนั้นดีสำหรับการค้นหาจำนวนพื้นที่ที่ใช้โดยตาราง (รวมดัชนี) แต่ถ้าคุณต้องการเปรียบเทียบว่าดัชนีพื้นที่บนตารางมีการใช้พื้นที่เท่าใดให้ใช้แบบสอบถามนี้:
SELECT
OBJECT_NAME(i.OBJECT_ID) AS TableName,
i.name AS IndexName,
i.index_id AS IndexID,
8 * SUM(a.used_pages) AS 'Indexsize(KB)'
FROM
sys.indexes AS i
JOIN sys.partitions AS p ON p.OBJECT_ID = i.OBJECT_ID AND p.index_id = i.index_id
JOIN sys.allocation_units AS a ON a.container_id = p.partition_id
WHERE
i.is_primary_key = 0 -- fix for size discrepancy
GROUP BY
i.OBJECT_ID,
i.index_id,
i.name
ORDER BY
OBJECT_NAME(i.OBJECT_ID),
i.index_id
where [i].[is_primary_key] = 0
คงคำตอบของเขาโดยการเพิ่ม ตอนนี้ขนาดควรตรงกับ
sp_spaceused
และขนาดที่เหมาะสมกับ ฉันวัด GBs ดังนั้นไม่กี่ megs ที่ไม่ตรงกันไม่มาก ฉันไม่สนใจขนาดที่แน่นอนเพียงแค่ความคิด
หากคุณต้องการคำนวณตัวเลขเดียวกันทั้งหมดที่อยู่ในหน้า 'คุณสมบัติตาราง - พื้นที่เก็บข้อมูล' ใน SSMS คุณต้องนับด้วยวิธีเดียวกับที่ทำใน SSMS (ทำงานกับเซิร์ฟเวอร์ sql 2005 และสูงกว่า ... และยัง ทำงานอย่างถูกต้องสำหรับตารางที่มีเขตข้อมูล LOB เนื่องจากการนับ "used_pages" ไม่เพียงพอที่จะแสดงขนาดดัชนีที่ถูกต้อง):
;with cte as (
SELECT
t.name as TableName,
SUM (s.used_page_count) as used_pages_count,
SUM (CASE
WHEN (i.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) as pages
FROM sys.dm_db_partition_stats AS s
JOIN sys.tables AS t ON s.object_id = t.object_id
JOIN sys.indexes AS i ON i.[object_id] = t.[object_id] AND s.index_id = i.index_id
GROUP BY t.name
)
select
cte.TableName,
cast((cte.pages * 8.)/1024 as decimal(10,3)) as TableSizeInMB,
cast(((CASE WHEN cte.used_pages_count > cte.pages
THEN cte.used_pages_count - cte.pages
ELSE 0
END) * 8./1024) as decimal(10,3)) as IndexSizeInMB
from cte
order by 2 desc
ขยายไปยังคำตอบ @xav ที่จัดการพาร์ติชันตารางเพื่อรับขนาดเป็น MB และ GB ทดสอบบน SQL Server 2008/2012 (แสดงความคิดเห็นในบรรทัดที่is_memory_optimized = 1
)
SELECT
a2.name AS TableName,
a1.rows as [RowCount],
--(a1.reserved + ISNULL(a4.reserved,0)) * 8 AS ReservedSize_KB,
--a1.data * 8 AS DataSize_KB,
--(CASE WHEN (a1.used + ISNULL(a4.used,0)) > a1.data THEN (a1.used + ISNULL(a4.used,0)) - a1.data ELSE 0 END) * 8 AS IndexSize_KB,
--(CASE WHEN (a1.reserved + ISNULL(a4.reserved,0)) > a1.used THEN (a1.reserved + ISNULL(a4.reserved,0)) - a1.used ELSE 0 END) * 8 AS UnusedSize_KB,
CAST(ROUND(((a1.reserved + ISNULL(a4.reserved,0)) * 8) / 1024.00, 2) AS NUMERIC(36, 2)) AS ReservedSize_MB,
CAST(ROUND(a1.data * 8 / 1024.00, 2) AS NUMERIC(36, 2)) AS DataSize_MB,
CAST(ROUND((CASE WHEN (a1.used + ISNULL(a4.used,0)) > a1.data THEN (a1.used + ISNULL(a4.used,0)) - a1.data ELSE 0 END) * 8 / 1024.00, 2) AS NUMERIC(36, 2)) AS IndexSize_MB,
CAST(ROUND((CASE WHEN (a1.reserved + ISNULL(a4.reserved,0)) > a1.used THEN (a1.reserved + ISNULL(a4.reserved,0)) - a1.used ELSE 0 END) * 8 / 1024.00, 2) AS NUMERIC(36, 2)) AS UnusedSize_MB,
--'| |' Separator_MB_GB,
CAST(ROUND(((a1.reserved + ISNULL(a4.reserved,0)) * 8) / 1024.00 / 1024.00, 2) AS NUMERIC(36, 2)) AS ReservedSize_GB,
CAST(ROUND(a1.data * 8 / 1024.00 / 1024.00, 2) AS NUMERIC(36, 2)) AS DataSize_GB,
CAST(ROUND((CASE WHEN (a1.used + ISNULL(a4.used,0)) > a1.data THEN (a1.used + ISNULL(a4.used,0)) - a1.data ELSE 0 END) * 8 / 1024.00 / 1024.00, 2) AS NUMERIC(36, 2)) AS IndexSize_GB,
CAST(ROUND((CASE WHEN (a1.reserved + ISNULL(a4.reserved,0)) > a1.used THEN (a1.reserved + ISNULL(a4.reserved,0)) - a1.used ELSE 0 END) * 8 / 1024.00 / 1024.00, 2) AS NUMERIC(36, 2)) AS UnusedSize_GB
FROM
(SELECT
ps.object_id,
SUM (CASE WHEN (ps.index_id < 2) THEN row_count ELSE 0 END) AS [rows],
SUM (ps.reserved_page_count) AS reserved,
SUM (CASE
WHEN (ps.index_id < 2) THEN (ps.in_row_data_page_count + ps.lob_used_page_count + ps.row_overflow_used_page_count)
ELSE (ps.lob_used_page_count + ps.row_overflow_used_page_count)
END
) AS data,
SUM (ps.used_page_count) AS used
FROM sys.dm_db_partition_stats ps
--===Remove the following comment for SQL Server 2014+
--WHERE ps.object_id NOT IN (SELECT object_id FROM sys.tables WHERE is_memory_optimized = 1)
GROUP BY ps.object_id) AS a1
LEFT OUTER JOIN
(SELECT
it.parent_id,
SUM(ps.reserved_page_count) AS reserved,
SUM(ps.used_page_count) AS used
FROM sys.dm_db_partition_stats ps
INNER JOIN sys.internal_tables it ON (it.object_id = ps.object_id)
WHERE it.internal_type IN (202,204)
GROUP BY it.parent_id) AS a4 ON (a4.parent_id = a1.object_id)
INNER JOIN sys.all_objects a2 ON ( a1.object_id = a2.object_id )
INNER JOIN sys.schemas a3 ON (a2.schema_id = a3.schema_id)
WHERE a2.type <> N'S' and a2.type <> N'IT'
--AND a2.name = 'MyTable' --Filter for specific table
--ORDER BY a3.name, a2.name
ORDER BY ReservedSize_MB DESC
สำหรับ Azure ฉันใช้สิ่งนี้:
คุณควรมี SSMS v17.x
ฉันใช้;
ด้วยสิ่งนี้ตามที่ผู้ใช้ พูดถึง :
เปิดของคุณDatabases
> และเลือกตาราง ,
จากนั้นกดปุ่มF7
คุณควรจะดูrow count
เป็น:
SSMS ที่นี่เชื่อมต่อกับฐานข้อมูล Azure
เราใช้การแบ่งตารางและมีปัญหากับแบบสอบถามที่ให้ไว้ข้างต้นเนื่องจากระเบียนที่ซ้ำกัน
สำหรับผู้ที่ต้องการสิ่งนี้คุณสามารถค้นหาแบบสอบถามด้านล่างซึ่งดำเนินการโดย SQL Server 2014 เมื่อสร้างรายงาน "การใช้ดิสก์ตามตาราง" ฉันถือว่ามันใช้งานได้กับ SQL Server รุ่นก่อนหน้าด้วย
มันทำงานเหมือนจับใจ
SELECT
a2.name AS [tablename],
a1.rows as row_count,
(a1.reserved + ISNULL(a4.reserved,0))* 8 AS reserved,
a1.data * 8 AS data,
(CASE WHEN (a1.used + ISNULL(a4.used,0)) > a1.data THEN (a1.used + ISNULL(a4.used,0)) - a1.data ELSE 0 END) * 8 AS index_size,
(CASE WHEN (a1.reserved + ISNULL(a4.reserved,0)) > a1.used THEN (a1.reserved + ISNULL(a4.reserved,0)) - a1.used ELSE 0 END) * 8 AS unused
FROM
(SELECT
ps.object_id,
SUM (
CASE
WHEN (ps.index_id < 2) THEN row_count
ELSE 0
END
) AS [rows],
SUM (ps.reserved_page_count) AS reserved,
SUM (
CASE
WHEN (ps.index_id < 2) THEN (ps.in_row_data_page_count + ps.lob_used_page_count + ps.row_overflow_used_page_count)
ELSE (ps.lob_used_page_count + ps.row_overflow_used_page_count)
END
) AS data,
SUM (ps.used_page_count) AS used
FROM sys.dm_db_partition_stats ps
WHERE ps.object_id NOT IN (SELECT object_id FROM sys.tables WHERE is_memory_optimized = 1)
GROUP BY ps.object_id) AS a1
LEFT OUTER JOIN
(SELECT
it.parent_id,
SUM(ps.reserved_page_count) AS reserved,
SUM(ps.used_page_count) AS used
FROM sys.dm_db_partition_stats ps
INNER JOIN sys.internal_tables it ON (it.object_id = ps.object_id)
WHERE it.internal_type IN (202,204)
GROUP BY it.parent_id) AS a4 ON (a4.parent_id = a1.object_id)
INNER JOIN sys.all_objects a2 ON ( a1.object_id = a2.object_id )
INNER JOIN sys.schemas a3 ON (a2.schema_id = a3.schema_id)
WHERE a2.type <> N'S' and a2.type <> N'IT'
ORDER BY a3.name, a2.name
-- Show the size of all the tables in a database sort by data size descending
SET NOCOUNT ON
DECLARE @TableInfo TABLE (tablename varchar(255), rowcounts int, reserved varchar(255), DATA varchar(255), index_size varchar(255), unused varchar(255))
DECLARE @cmd1 varchar(500)
SET @cmd1 = 'exec sp_spaceused ''?'''
INSERT INTO @TableInfo (tablename,rowcounts,reserved,DATA,index_size,unused)
EXEC sp_msforeachtable @command1=@cmd1
SELECT * FROM @TableInfo ORDER BY Convert(int,Replace(DATA,' KB','')) DESC
การเปลี่ยนแปลงเล็กน้อยในคำตอบของ Mar_cเนื่องจากฉันได้กลับมาที่หน้านี้บ่อยๆสั่งโดยแถวแรกสุด:
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
--p.rows DESC --Uncomment to order by amount rows instead of size in KB.
SUM(a.total_pages) DESC
สิ่งนี้จะทำให้คุณมีขนาดและบันทึกการนับสำหรับแต่ละตาราง
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
-- Get a list of tables and their sizes on disk
ALTER PROCEDURE [dbo].[sp_Table_Sizes]
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE @table_name VARCHAR(500)
DECLARE @schema_name VARCHAR(500)
DECLARE @tab1 TABLE(
tablename VARCHAR (500) collate database_default
,schemaname VARCHAR(500) collate database_default
)
CREATE TABLE #temp_Table (
tablename sysname
,row_count INT
,reserved VARCHAR(50) collate database_default
,data VARCHAR(50) collate database_default
,index_size VARCHAR(50) collate database_default
,unused VARCHAR(50) collate database_default
)
INSERT INTO @tab1
SELECT Table_Name, Table_Schema
FROM information_schema.tables
WHERE TABLE_TYPE = 'BASE TABLE'
DECLARE c1 CURSOR FOR
SELECT Table_Schema + '.' + Table_Name
FROM information_schema.tables t1
WHERE TABLE_TYPE = 'BASE TABLE'
OPEN c1
FETCH NEXT FROM c1 INTO @table_name
WHILE @@FETCH_STATUS = 0
BEGIN
SET @table_name = REPLACE(@table_name, '[','');
SET @table_name = REPLACE(@table_name, ']','');
-- make sure the object exists before calling sp_spacedused
IF EXISTS(SELECT id FROM sysobjects WHERE id = OBJECT_ID(@table_name))
BEGIN
INSERT INTO #temp_Table EXEC sp_spaceused @table_name, false;
END
FETCH NEXT FROM c1 INTO @table_name
END
CLOSE c1
DEALLOCATE c1
SELECT t1.*
,t2.schemaname
FROM #temp_Table t1
INNER JOIN @tab1 t2 ON (t1.tablename = t2.tablename )
ORDER BY schemaname,t1.tablename;
DROP TABLE #temp_Table
END
{ }
) บนแถบเครื่องมือตัวแก้ไขเพื่อจัดรูปแบบและเน้นไวยากรณ์!
รับขนาดตารางทั้งหมดในฐานข้อมูลเดียวคุณสามารถใช้แบบสอบถามนี้:
Exec sys.sp_MSforeachtable ' sp_spaceused "?" '
และคุณสามารถเปลี่ยนเพื่อแทรกผลลัพธ์ทั้งหมดลงในตารางอุณหภูมิและหลังจากนั้นเลือกจากตารางอุณหภูมิ
Insert into #TempTable Exec sys.sp_MSforeachtable ' sp_spaceused "?" '
Select * from #TempTable
จากพรอมต์คำสั่งโดยใช้OSQL :
OSQL -E -d <*databasename*> -Q "exec sp_msforeachtable 'sp_spaceused [?]'" > result.txt
นี่คือวิธีในการรับขนาดตารางทั้งหมดอย่างรวดเร็วด้วยขั้นตอนต่อไปนี้:
เขียนคำสั่ง T-SQL ที่กำหนดเพื่อแสดงรายการตารางฐานข้อมูลทั้งหมด:
select 'exec sp_spaceused ' + TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_TYPE = 'BASE TABLE'
ตอนนี้คัดลอกรายการของตารางฐานข้อมูลและคัดลอกลงในหน้าต่างตัววิเคราะห์แบบสอบถามใหม่
exec sp_spaceused table1
exec sp_spaceused table2
exec sp_spaceused table3
exec sp_spaceused table4
exec sp_spaceused table5
ในตัววิเคราะห์คิวรี SQL เลือกจากแถบเครื่องมือตัวเลือกตัวเลือกResults to file ( Ctrl+ Shift+ F)
ตอนนี้จนตีExecuteปุ่มสีแดงที่ทำเครื่องหมายไว้จากด้านบนแถบเครื่องมือ
ขณะนี้ขนาดฐานข้อมูลของตารางทั้งหมดถูกจัดเก็บในไฟล์บนคอมพิวเตอร์ของคุณ
ฉันเพิ่มคอลัมน์อีกสองสามรายการที่ด้านบนของคำตอบ marc_s:
with fs
as
(
select i.object_id,
p.rows AS RowCounts,
SUM(a.total_pages) * 8 AS TotalSpaceKb
from sys.indexes i 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
i.OBJECT_ID > 255
GROUP BY
i.object_id,
p.rows
)
SELECT
t.NAME AS TableName,
fs.RowCounts,
fs.TotalSpaceKb,
t.create_date,
t.modify_date,
( select COUNT(1)
from sys.columns c
where c.object_id = t.object_id ) TotalColumns
FROM
sys.tables t INNER JOIN
fs ON t.OBJECT_ID = fs.object_id
WHERE
t.NAME NOT LIKE 'dt%'
AND t.is_ms_shipped = 0
ORDER BY
t.Name
โพสต์ของฉันเกี่ยวข้องเฉพาะกับ SQL Server 2000 และได้รับการทดสอบให้ทำงานในสภาพแวดล้อมของฉัน
รหัสนี้เข้าถึงฐานข้อมูลที่เป็นไปได้ทั้งหมดของอินสแตนซ์เดียวไม่ใช่ฐานข้อมูลเดียว
ฉันใช้ตารางชั่วคราวสองตารางเพื่อช่วยรวบรวมข้อมูลที่เหมาะสมจากนั้นถ่ายโอนข้อมูลผลลัพธ์ลงในตาราง 'สด'
ข้อมูลที่ส่งคืนคือ: DatabaseName, DatabaseTableName, แถว (ในตาราง), ข้อมูล (ขนาดของตารางในหน่วย KB ที่ดูเหมือนจะเป็น), ข้อมูลรายการ (ฉันพบว่ามีประโยชน์สำหรับการรู้เมื่อฉันเรียกใช้สคริปต์ครั้งล่าสุด)
ความตกต่ำของรหัสนี้คือฟิลด์ 'data' ไม่ได้ถูกจัดเก็บในรูปแบบ int (ตัวอักษร 'KB' จะถูกเก็บไว้ในฟิลด์นั้น) และนั่นจะเป็นประโยชน์ (แต่ไม่จำเป็นทั้งหมด) สำหรับการเรียงลำดับ
หวังว่ารหัสนี้จะช่วยให้ใครบางคนที่นั่นและช่วยพวกเขาในบางเวลา!
CREATE PROCEDURE [dbo].[usp_getAllDBTableSizes]
AS
BEGIN
SET NOCOUNT OFF
CREATE TABLE #DatabaseTables([dbname] sysname,TableName sysname)
CREATE TABLE #AllDatabaseTableSizes(Name sysname,[rows] VARCHAR(18), reserved VARCHAR(18), data VARCHAR(18), index_size VARCHAR(18), unused VARCHAR(18))
DECLARE @SQL nvarchar(4000)
SET @SQL='select ''?'' AS [Database], Table_Name from [?].information_schema.tables WHERE TABLE_TYPE = ''BASE TABLE'' '
INSERT INTO #DatabaseTables(DbName, TableName)
EXECUTE sp_msforeachdb @Command1=@SQL
DECLARE AllDatabaseTables CURSOR LOCAL READ_ONLY FOR
SELECT TableName FROM #DatabaseTables
DECLARE AllDatabaseNames CURSOR LOCAL READ_ONLY FOR
SELECT DBName FROM #DatabaseTables
DECLARE @DBName sysname
OPEN AllDatabaseNames
DECLARE @TName sysname
OPEN AllDatabaseTables
WHILE 1=1 BEGIN
FETCH NEXT FROM AllDatabaseNames INTO @DBName
FETCH NEXT FROM AllDatabaseTables INTO @TName
IF @@FETCH_STATUS<>0 BREAK
INSERT INTO #AllDatabaseTableSizes
EXEC ( 'EXEC ' + @DBName + '.dbo.sp_spaceused ' + @TName)
END
--http://msdn.microsoft.com/en-us/library/aa175920(v=sql.80).aspx
INSERT INTO rsp_DatabaseTableSizes (DatabaseName, name, [rows], data)
SELECT [dbname], name, [rows], data FROM #DatabaseTables
INNER JOIN #AllDatabaseTableSizes
ON #DatabaseTables.TableName = #AllDatabaseTableSizes.Name
GROUP BY [dbname] , name, [rows], data
ORDER BY [dbname]
--To be honest, I have no idea what exact duplicates we are dropping
-- but in my case a near enough approach has been good enough.
DELETE FROM [rsp_DatabaseTableSizes]
WHERE name IN
(
SELECT name
FROM [rsp_DatabaseTableSizes]
GROUP BY name
HAVING COUNT(*) > 1
)
DROP TABLE #DatabaseTables
DROP TABLE #AllDatabaseTableSizes
CLOSE AllDatabaseTables
DEALLOCATE AllDatabaseTables
CLOSE AllDatabaseNames
DEALLOCATE AllDatabaseNames
END
--EXEC [dbo].[usp_getAllDBTableSizes]
ในกรณีที่คุณจำเป็นต้องรู้ตารางrsp_DatabaseTableSizesถูกสร้างขึ้นผ่าน:
CREATE TABLE [dbo].[rsp_DatabaseSizes](
[DatabaseName] [varchar](1000) NULL,
[dbSize] [decimal](15, 2) NULL,
[DateUpdated] [smalldatetime] NULL
) ON [PRIMARY]
GO
ในฐานะที่เป็นส่วนขยายที่ง่ายต่อการตอบของ marc_s (ส่วนที่ได้รับการยอมรับ) สิ่งนี้จะถูกปรับเพื่อส่งกลับจำนวนคอลัมน์และอนุญาตให้มีการกรอง:
SELECT *
FROM
(
SELECT
t.NAME AS TableName,
s.Name AS SchemaName,
p.rows AS RowCounts,
COUNT(DISTINCT c.COLUMN_NAME) as ColumnCount,
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
INNER JOIN
INFORMATION_SCHEMA.COLUMNS c ON t.NAME = c.TABLE_NAME
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
) AS Result
WHERE
RowCounts > 1000
AND ColumnCount > 10
ORDER BY
UsedSpaceKB DESC
การตอบคำถามบน @Mark ข้างต้นเพิ่ม @ updateusage = 'true' เพื่อบังคับสถิติขนาดล่าสุด ( https://msdn.microsoft.com/en-us/library/ms188776.aspx ):
SET NOCOUNT ON
DECLARE @TableInfo TABLE (tablename varchar(255), rowcounts int, reserved varchar(255), DATA varchar(255), index_size varchar(255), unused varchar(255))
DECLARE @cmd1 varchar(500)
SET @cmd1 = 'exec sp_spaceused @objname =''?'', @updateusage =''true'' '
INSERT INTO @TableInfo (tablename,rowcounts,reserved,DATA,index_size,unused)
EXEC sp_msforeachtable @command1=@cmd1
SELECT * FROM @TableInfo ORDER BY Convert(int,Replace(DATA,' KB','')) DESC
นี่คือแบบสอบถามตัวอย่างเพื่อรับตารางที่มีขนาดใหญ่กว่า 1GB เรียงจากขนาดจากมากไปน้อย
USE YourDB
GO
DECLARE @Mult float = 8
SET @Mult = @Mult / POWER(2, 20) -- Use POWER(2, 10) for MBs
; WITH CTE AS
(
SELECT
i.object_id,
Rows = MAX(p.rows),
TotalSpaceGB = ROUND(SUM(a.total_pages) * @Mult, 0),
UsedSpaceGB = ROUND(SUM(a.used_pages) * @Mult, 0)
FROM
sys.indexes i
JOIN
sys.partitions p ON i.object_id = p.object_id AND i.index_id = p.index_id
JOIN
sys.allocation_units a ON p.partition_id = a.container_id
WHERE
i.object_id > 255
GROUP BY
i.object_id
HAVING
SUM(a.total_pages) * @Mult > 1
)
SELECT
SchemaName = s.name,
TableName = t.name,
c.TotalSpaceGB,
c.UsedSpaceGB,
UnusedSpaceGB = c.TotalSpaceGB - c.UsedSpaceGB,
[RowCount] = c.Rows
FROM
CTE c
JOIN
sys.tables t ON t.object_id = c.object_id
JOIN
sys.schemas s ON t.schema_id = s.schema_id
ORDER BY
c.TotalSpaceGB DESC