Nhận kích thước của tất cả các bảng trong cơ sở dữ liệu


1271

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ụ?


vai trò nào bạn có quyền truy cập? Bạn có phải là DBA, hay điều này được quản lý thông qua máy chủ web, máy khách hoặc tương tự?
Rob Allen


@Rob ALLen Tôi có toàn quyền truy cập vào cơ sở dữ liệu, vì vậy một tập lệnh yêu cầu bất kỳ vai trò nào là đủ.
Eric


Đối với Azure, tôi đã sử dụng cái này
Irf

Câu trả lời:


2594
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

7
Câu hỏi ngớ ngẩn, nhưng có thể là truy vấn này có thể gây ra khóa hàng?
GEMI

7
Các chỉ mục cũng sử dụng không gian và lượng không gian được sử dụng bởi các chỉ mục có thể được tìm thấy với truy vấn này bên dưới.
Jens Frandsen

6
Tập lệnh của bạn có vấn đề với các chỉ mục được lọc: Đối với mỗi chỉ mục được lọc cho một bảng nhất định, tôi thấy một hàng bổ sung có tên của bảng đó trong kết quả. "RowCounts" của mỗi hàng bổ sung đó tương ứng với số lượng hàng được bao phủ bởi một trong các chỉ mục được lọc. (trên Sql2012)
Akos Lukacs

37
@Todd: một số người muốn nó được đặt hàng theo cách đó - những người khác muốn nó theo tên bảng - hãy chọn, điều chỉnh mã khi cần thiết ....
marc_s

12
Nếu các bảng của bạn được phân vùng, chúng sẽ hiển thị nhiều lần mà không có bất kỳ dấu hiệu nào về những gì đang diễn ra. Bạn có thể thêm p.partition_number vào danh sách chọn hoặc bạn có thể SUM (p.Rows) và xóa nó khỏi nhóm bằng cách.
PRman

561

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

  1. Nhấp chuột phải vào cơ sở dữ liệu
  2. Điều hướng đến Báo cáo> Báo cáo chuẩn> Sử dụng đĩa theo bảng

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


54
Trong Management Studio 2012, bạn có thể thực hiện: Chi tiết Explorer-Object Explorer (F7) và điều hướng đến "Bảng" trong Object Explorer. Trong Chi tiết nhấp chuột phải vào tiêu đề và chọn cột kích thước.
ValGe

3
để tư vấn chức năng mới với SSMS 2012. Đối với chúng tôi, những người chơi cũ, chúng tôi chưa bao giờ có sẵn điều này. Vì vậy, chúng tôi đã làm theo cách TSQL cũ :)
GoldBishop

3
Dù bạn có tin hay không, đôi khi chỉ những người bình thường (nhà phát triển) muốn xem thông tin này và chúng tôi không có quyền sử dụng báo cáo được xây dựng nhưng chúng tôi có thể chạy TSQL trong câu trả lời được chấp nhận. :) FYI (BTW, tôi vẫn nêu lên câu trả lời của bạn)
Andrew Steitz

8
Dường như không có mặt trong Azure SQL :-(
Simon_Weaver

1
Tôi biết điều đó không nghiêm trọng, nhưng, làm ơn, bạn chỉ cần đẩy các nhóm bên lề ra khỏi kỹ thuật & công nghệ với dòng lý luận này được lặp đi lặp lại ở mọi nơi. Bạn nên học cả hai, nhưng bạn cũng không nên trừng phạt mọi người vì đã sử dụng các tiện ích tiết kiệm thời gian để làm việc thông minh hơn và nhanh hơn. (Mặc dù SSMS dường như là một "tiện ích làm chậm" đôi khi ...: X) Về mặt cá nhân, các chỉ số cho dữ liệu dạng bảng thường rõ ràng hơn trong GUI, mặc dù các công cụ do Microsoft xây dựng có xu hướng là ngoại lệ cho mọi thứ liên quan đến UI.
Julia McGuigan

102

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]".


3
Điều này rất gọn gàng mặc dù việc sử dụng sp_msforeachtabletrong SSMS dễ dàng có thể kích hoạt System.OutOfMemoryExceptionnế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ả.
syirecton-dj

1
Vấn đề chính tôi có thể thấy với sp_spacesuse là nó dường như trả về dữ liệu ở định dạng có thể đọc được của con người (ví dụ: trong cột 'dành riêng' trong trường hợp của tôi có '152 KB'). Tôi giả sử điều này sẽ chuyển sang MB / GB khi thích hợp. Điều này rõ ràng hữu ích trong rất nhiều tình huống nhưng không phải nếu bạn cần áp dụng một số logic dựa trên kích thước, hoặc muốn so sánh các giá trị hoặc bất cứ điều gì. Tôi đã tìm cách tắt nó đi, nhưng tôi không thể phát hiện ra (Tôi đang sử dụng SQL Server 2005 :()
DarthPablo

55

Đâ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

nhập mô tả hình ảnh ở đây

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.

nhập mô tả hình ảnh ở đây


Có, SSMS trong Azure thiếu một số tính năng so với phiên bản cục bộ.
Sparrow

@batmaci Không chắc chắn liệu điều này có hoạt động hay không khi bạn đưa ra nhận xét về cơ sở dữ liệu Azure SQL, nhưng dường như ít nhất nó hiện đang hoạt động một phần trong các phiên bản SSMS gần đây. Đối với tôi có vẻ như truy vấn cho siêu dữ liệu bảng đã hết thời gian, nhưng trước khi nó dường như trả về một vài (3-10) bảng có giá trị, bao gồm (đáng tin cậy) bảng đã chọn. Chọn một bảng và nhấp vào làm mới để xem bảng bạn muốn nếu nó không được hiển thị.
pcdev

Azure không phải là "Máy chủ SQL" thực sự (ha ha)
Kỹ sư đảo ngược

Tôi đã sử dụng cái này cho Azure, cảm ơn với (cộng một),
Irf 26/07/19

Bạn cũng có thể xuất danh sách trong tệp CSV bằng cách sử dụng tiện ích như NirSoft SysExporter: nirsoft.net/utils/sysexp.html
Tối đa

39

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

Sau khi thấy những điều trên bằng cách sử dụng foreach và SP sẽ viết một cái gì đó như thế này, vui mừng tôi cuộn xuống để thấy nó tiết kiệm cho tôi một chút thời gian.
Brad

37
 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 [?]'

5
Lén lút - bạn đã thay đổi từ exec sp_helpdbđó không hiển thị bất cứ điều gì về các bảng, exec sp_spaceusedtrong đó - 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.
marc_s

4
exec sp_MSForEachTable 'exec sp_spaceuse [?]'
Paul

27

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

Lý do tổng hợp cột Indexsize (KB) cho một bảng cụ thể không đồng ý với index_size từ sp_spaceuse là gì?
Derek

@Derek Đã sửa câu trả lời của anh ấy bằng cách thêm where [i].[is_primary_key] = 0. Bây giờ kích thước phải phù hợp.
CodeAngry

Cảm ơn bạn, nhưng điều này thực sự cũng không hiệu quả. Tôi có một cơ sở dữ liệu kiểm tra (rất nhỏ), bảng quan tâm có hai chỉ mục - một chỉ mục được phân cụm chính trên một cột và một chỉ mục không được phân cụm trên hai trong số các cột khác. Truy vấn này cho biết mỗi người trong số họ đang sử dụng 16kB, nhưng sp_spaceuse cho biết tổng mức sử dụng chỉ mục là 24kB. Một phần của sự nhầm lẫn của tôi là: So sánh truy vấn này với "Được sử dụngSpaceKB" của câu trả lời được chấp nhận, tôi không thấy sự khác biệt thực sự. Cùng tham gia, chỉ thiếu việc bổ sung sys.tables. Tôi có thiếu thứ gì không, hay truy vấn này vốn đã bị hỏng?
Derek

Tôi có cơ sở dữ liệu lớn. Và kích thước phù hợp với 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.
CodeAngry

14

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

14

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

cũng sắp xếp thứ tự tốt hơn.
Pxtl

Đây phải là câu trả lời hàng đầu.
Baodad

14

Đố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;

nhập mô tả hình ảnh ở đây

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: nhập mô tả hình ảnh ở đây

SSMS ở đây được kết nối với cơ sở dữ liệu Azure


3
F7 bị lạm dụng rất nhiều.
cskwg

1
Tôi không có ý tưởng này tồn tại, tôi hơi xấu hổ về bản thân mình: p Cảm ơn!
lollancf37

Nó có vấn đề với các bảng được tối ưu hóa bộ nhớ, (tôi chỉ thử nghiệm sau khi xem bài đăng này :)
Amirreza

11

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

Cảm ơn về tập lệnh khớp với cách SSMS thực hiện và xử lý đúng các phân vùng.
Mike

8
-- 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

8

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 

5

Đ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

2
Nếu bạn đăng các mẫu mã, XML hoặc dữ liệu, XIN làm nổi bật các dòng đó trong trình soạn thảo văn bản và nhấp vào nút "mẫu mã" ( { }) 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ó!
marc_s

4

Để 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

3

Từ một dấu nhắc lệnh bằng OSQL :

OSQL -E -d <*databasename*> -Q "exec sp_msforeachtable 'sp_spaceused [?]'" > result.txt

3

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:

  1. 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'
  2. 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
  3. 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).

  4. 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 .

  5. 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.

    Nhập mô tả hình ảnh ở đây


2

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

1

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

1

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

Sau khi bạn tham gia bảng Cột, bạn không còn có không gian bảng phù hợp. Áp dụng bên ngoài sẽ là sửa chữa.
dreamca4er

0

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

0

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.