Tôi đã thừa hưởng một cơ sở dữ liệu SQL Server khá lớn. Nó dường như chiếm nhiều không gian hơn tôi mong đợi, dựa trên dữ liệu chứa trong đó.
Có một cách dễ dàng để xác định bao nhiêu không gian trên đĩa mà mỗi bảng đang tiêu thụ?
Tôi đã thừa hưởng một cơ sở dữ liệu SQL Server khá lớn. Nó dường như chiếm nhiều không gian hơn tôi mong đợi, dựa trên dữ liệu chứa trong đó.
Có một cách dễ dàng để xác định bao nhiêu không gian trên đĩa mà mỗi bảng đang tiêu thụ?
Câu trả lời:
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
Nếu bạn đang sử dụng SQL Server Management Studio (SSMS), thay vì chạy truy vấn ( trong trường hợp của tôi trả về các hàng trùng lặp ), bạn có thể chạy báo cáo chuẩn .
Lưu ý: Mức độ tương thích cơ sở dữ liệu phải được đặt thành 90 trở lên để hoạt động chính xác. Xem http://msdn.microsoft.com/en-gb/l Library / bb510680.aspx
sp_spaceuse có thể cung cấp cho bạn thông tin về không gian đĩa được sử dụng bởi một bảng, chế độ xem được lập chỉ mục hoặc toàn bộ cơ sở dữ liệu.
Ví dụ:
USE MyDatabase; GO
EXEC sp_spaceused N'User.ContactInfo'; GO
Điều này báo cáo thông tin sử dụng đĩa cho bảng ContactInfo.
Để sử dụng điều này cho tất cả các bảng cùng một lúc:
USE MyDatabase; GO
sp_msforeachtable 'EXEC sp_spaceused [?]' GO
Bạn cũng có thể nhận được mức sử dụng đĩa từ bên phải chức năng Báo cáo chuẩn của SQL Server. Để đến báo cáo này, điều hướng từ đối tượng máy chủ trong Object Explorer, di chuyển xuống đối tượng Cơ sở dữ liệu, sau đó bấm chuột phải vào bất kỳ cơ sở dữ liệu nào. Từ menu xuất hiện, chọn Báo cáo, sau đó là Báo cáo chuẩn và sau đó "Sử dụng đĩa theo phân vùng: [DatabaseName]".
sp_msforeachtable
trong SSMS dễ dàng có thể kích hoạt System.OutOfMemoryException
nếu bạn có số lượng bảng lớn, vì vậy có thể nên sử dụng bảng tạm thời để lưu trữ kết quả.
Đây là một phương pháp khác: sử dụng SQL Server Management Studio , trong Object Explorer , truy cập cơ sở dữ liệu của bạn và chọn Bảng
Sau đó mở Chi tiết thám hiểm đối tượng (bằng cách nhấn F7 hoặc đi đến Xem-> Chi tiết thám hiểm đối tượng ). Trong trang chi tiết thám hiểm đối tượng, nhấp chuột phải vào tiêu đề cột và bật các cột mà bạn muốn thấy trong trang. Bạn có thể sắp xếp dữ liệu theo bất kỳ cột nào.
Sau một số tìm kiếm, tôi không thể tìm thấy một cách dễ dàng để có được thông tin trên tất cả các bảng. Có một thủ tục được lưu trữ tiện dụng có tên sp_spaceuse sẽ trả về tất cả không gian được sử dụng bởi cơ sở dữ liệu. Nếu được cung cấp với một tên bảng, nó sẽ trả về không gian được sử dụng bởi bảng đó. Tuy nhiên, kết quả được trả về bởi thủ tục được lưu trữ là không thể sắp xếp được, vì các cột là giá trị ký tự.
Kịch bản sau đây sẽ tạo ra thông tin tôi đang tìm kiếm.
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'
Đối với tất cả các bảng, hãy sử dụng .. (thêm từ nhận xét của Paul)
exec sp_MSForEachTable 'exec sp_spaceused [?]'
exec sp_helpdb
đó không hiển thị bất cứ điều gì về các bảng, exec sp_spaceused
trong đó - nhưng chỉ cho một bảng tại một thời điểm ... nó không cung cấp cho bạn tổng quan về những bảng bạn có và số lượng hàng chúng có và cách thức nhiều không gian họ chiếm.
Các truy vấn trên rất tốt cho việc tìm lượng không gian được sử dụng bởi bảng (bao gồm các chỉ mục), nhưng nếu bạn muốn so sánh lượng không gian được sử dụng bởi các chỉ mục trên bảng, hãy sử dụng truy vấn này:
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
. Bây giờ kích thước phải phù hợp.
sp_spaceused
. Tôi đo GB để một vài megs không khớp không nhiều. Tôi không quan tâm đến kích thước chính xác, chỉ là một ý tưởng.
Nếu bạn cần tính toán chính xác các số giống nhau, trên trang 'thuộc tính bảng - lưu trữ' trong SSMS, bạn cần tính chúng với cùng một phương thức như đã thực hiện trong SSMS (hoạt động cho máy chủ sql 2005 trở lên ... và cả hoạt động chính xác cho các bảng có trường LOB - vì chỉ tính "used_pages" là không đủ để hiển thị kích thước chỉ mục chính xác):
;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
Mở rộng cho câu trả lời @xav đã xử lý các phân vùng bảng để có kích thước tính bằng MB và GB. Đã thử nghiệm trên SQL Server 2008/2012 (Đã nhận xét một dòng trong đó 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
Đối với Azure tôi đã sử dụng điều này:
Bạn nên có SSMS v17.x
Tôi đã sử dụng;
Với điều này, như User Sparrow đã đề cập :
Mở Databases
> và chọn Bảng , sau
đó nhấn phím F7
Bạn sẽ thấy row count
như sau:
SSMS ở đây được kết nối với cơ sở dữ liệu Azure
Chúng tôi sử dụng phân vùng bảng và gặp một số rắc rối với các truy vấn được cung cấp ở trên do các bản ghi trùng lặp.
Đối với những người cần điều này, bạn có thể tìm thấy bên dưới truy vấn được chạy bởi SQL Server 2014 khi tạo báo cáo "Sử dụng đĩa theo bảng". Tôi giả sử nó cũng hoạt động với các phiên bản trước của SQL Server.
Nó hoạt động như một say mê.
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
Một thay đổi nhỏ về câu trả lời của Mar_c , vì tôi thường xuyên quay lại trang này, được đặt hàng bởi hầu hết các hàng đầu tiên:
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
Điều này sẽ cung cấp cho bạn các kích thước và số lượng bản ghi cho mỗi bảng.
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
{ }
) trên thanh công cụ của trình soạn thảo để định dạng độc đáo và cú pháp làm nổi bật nó!
Để có được tất cả kích thước bảng trong một cơ sở dữ liệu, bạn có thể sử dụng truy vấn này:
Exec sys.sp_MSforeachtable ' sp_spaceused "?" '
Và bạn có thể thay đổi nó để chèn tất cả kết quả vào bảng tạm thời và sau đó chọn từ bảng tạm thời.
Insert into #TempTable Exec sys.sp_MSforeachtable ' sp_spaceused "?" '
Select * from #TempTable
Từ một dấu nhắc lệnh bằng OSQL :
OSQL -E -d <*databasename*> -Q "exec sp_msforeachtable 'sp_spaceused [?]'" > result.txt
Dưới đây là cách để có được kích thước của tất cả các bảng một cách nhanh chóng với các bước sau:
Viết các lệnh T-SQL đã cho để liệt kê tất cả các bảng cơ sở dữ liệu:
select 'exec sp_spaceused ' + TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_TYPE = 'BASE TABLE'
Bây giờ sao chép danh sách các bảng cơ sở dữ liệu và sao chép nó vào một cửa sổ phân tích truy vấn mới
exec sp_spaceused table1
exec sp_spaceused table2
exec sp_spaceused table3
exec sp_spaceused table4
exec sp_spaceused table5
Trong trình phân tích truy vấn SQL , chọn từ tùy chọn thanh công cụ hàng đầu Kết quả cho tệp ( Ctrl+ Shift+ F).
Bây giờ cuối cùng nhấn nút Execute được đánh dấu màu đỏ từ thanh công cụ trên .
Kích thước cơ sở dữ liệu của tất cả các bảng hiện được lưu trữ trong một tệp trên máy tính của bạn.
Tôi đã thêm một vài cột trên đầu câu trả lời 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
Bài đăng của tôi chỉ liên quan đến SQL Server 2000 và đã được thử nghiệm để hoạt động trong môi trường của tôi.
Mã này truy cập Tất cả các cơ sở dữ liệu có thể có của một thể hiện , không chỉ một cơ sở dữ liệu.
Tôi sử dụng hai bảng tạm thời để giúp thu thập dữ liệu phù hợp và sau đó kết quả vào một bảng 'Sống'.
Dữ liệu được trả về là: DatabaseName, DatabaseTableName, Rows (trong Bảng), dữ liệu (kích thước của bảng có vẻ như KB), dữ liệu nhập (Tôi thấy điều này hữu ích khi biết lần cuối tôi chạy tập lệnh).
Sự sụp đổ của mã này là trường 'dữ liệu' không được lưu dưới dạng int (Các ký tự 'KB' được giữ trong trường đó) và điều đó sẽ hữu ích (nhưng không hoàn toàn cần thiết) để sắp xếp.
Hy vọng mã này sẽ giúp ai đó ngoài kia và tiết kiệm thời gian cho họ!
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]
Trong trường hợp bạn cần biết, bảng rsp_DatabaseTableSizes đã được tạo thông qua:
CREATE TABLE [dbo].[rsp_DatabaseSizes](
[DatabaseName] [varchar](1000) NULL,
[dbSize] [decimal](15, 2) NULL,
[DateUpdated] [smalldatetime] NULL
) ON [PRIMARY]
GO
Là một phần mở rộng đơn giản cho câu trả lời của marc_s ( câu trả lời đã được chấp nhận), điều này được điều chỉnh để trả về số lượng cột và cho phép lọc:
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
Riffing trên @Mark trả lời ở trên, đã thêm @ updateusage = 'true' để buộc các số liệu thống kê kích thước mới nhất ( https://msdn.microsoft.com/en-us/l 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
Dưới đây là một truy vấn mẫu để có được các bảng lớn hơn 1GB được sắp xếp theo kích thước giảm dần.
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