127

How to find the size of a table in SQL?

Luke Girvin
  • 13,221
  • 9
  • 64
  • 84
anjum
  • 2,363
  • 6
  • 28
  • 25

11 Answers11

156

SQL Server:-

sp_spaceused 'TableName'

Or in management studio: Right Click on table -> Properties -> Storage

MySQL:-

SELECT table_schema, table_name, data_length, index_length FROM information_schema.tables

Sybase:-

sp_spaceused 'TableName'

Oracle:- how-do-i-calculate-tables-size-in-oracle

Community
  • 1
  • 1
Kashif
  • 14,071
  • 18
  • 66
  • 98
  • 1
    Note, for MySQL `data_length` is the size of the table in bytes, not the number of rows. See: https://dev.mysql.com/doc/refman/8.0/en/tables-table.html – Ceasar Jul 26 '19 at 22:04
65

Updating (after more than 10 years!) with an improved version using suggestions from the comments:

This gives you a list of all your tables in order of reserved size, ordered from largest to smallest.

This uses the same method as the previous one, but makes the results table a variable so it doesn't have to be cleaned up when done. Also it converts all the values to actual integers so they can be easily viewed and sorted.

DECLARE @tmpTableSizes TABLE
(
    tableName    VARCHAR(100),
    numberofRows VARCHAR(100),
    reservedSize VARCHAR(50),
    dataSize     VARCHAR(50),
    indexSize    VARCHAR(50),
    unusedSize   VARCHAR(50)
)

INSERT @tmpTableSizes 
    EXEC sp_MSforeachtable @command1="EXEC sp_spaceused '?'"

SELECT
    tableName,
    CAST(numberofRows AS INT)                              'numberOfRows',
    CAST(LEFT(reservedSize, LEN(reservedSize) - 3) AS INT) 'reservedSize KB',
    CAST(LEFT(dataSize, LEN(dataSize) - 3) AS INT)         'dataSize KB',
    CAST(LEFT(indexSize, LEN(indexSize) - 3) AS INT)       'indexSize KB',
    CAST(LEFT(unusedSize, LEN(unusedSize) - 3) AS INT)     'unusedSize KB'
    FROM
        @tmpTableSizes
    ORDER BY
        [reservedSize KB] DESC

Previous Version before 2023-02-21:

Combining the answers from ratty's and Haim's posts (including comments) I've come up with this, which for SQL Server seems to be the most elegant so far:

-- DROP TABLE #tmpTableSizes
CREATE TABLE #tmpTableSizes
(
    tableName varchar(100),
    numberofRows varchar(100),
    reservedSize varchar(50),
    dataSize varchar(50),
    indexSize varchar(50),
    unusedSize varchar(50)
)
insert #tmpTableSizes
EXEC sp_MSforeachtable @command1="EXEC sp_spaceused '?'"


select  * from #tmpTableSizes
order by cast(LEFT(reservedSize, LEN(reservedSize) - 4) as int)  desc

This gives you a list of all your tables in order of reserved size, ordered from largest to smallest.

Mark Meuer
  • 7,200
  • 6
  • 43
  • 64
  • I was going to post this very script - let's hope he's using SQL Server. – SqlRyan Sep 15 '10 at 17:18
  • 3
    Excellent script - except, it should read LEN(...) - 3, not minus 4. The values come back like this: "3746520 KB" so it's just the last 3 characters which need chopping off. But... cool to see how a posting from 7 years ago is as useful today as it was back in 2010 !! – Mike Gledhill Aug 14 '17 at 09:17
  • 2
    make it a variable table and you won't have to drop it. "declare @tmpTableSizes TABLE " – ARLibertarian May 30 '19 at 15:37
  • I wonder how to include the schema name with this example? There is an example below which includes schema name but not indexes. – Amadeus Stevenson Jul 13 '23 at 14:31
  • @AmadeusStevenson Actually, the tablename column already includes the schema name. At least that's what I'm seeing when running locally. – Mark Meuer Jul 20 '23 at 16:58
33

SQL Server provides a built-in stored procedure that you can run to easily show the size of a table, including the size of the indexes… which might surprise you.

Syntax:

 sp_spaceused 'Tablename'

see in :

http://www.howtogeek.com/howto/database/determine-size-of-a-table-in-sql-server/

Nate Anderson
  • 18,334
  • 18
  • 100
  • 135
Haim Evgi
  • 123,187
  • 45
  • 217
  • 223
25

A query (modification of https://stackoverflow.com/a/7892349/1737819) to find a custom name table size in GB. You might try this, replace 'YourTableName' with the name of your table.

SELECT 
    t.NAME AS TableName,    
    p.rows AS RowCounts,
    CONVERT(DECIMAL,SUM(a.total_pages)) * 8 / 1024 / 1024 AS TotalSpaceGB, 
    SUM(a.used_pages)  * 8 / 1024 / 1024 AS UsedSpaceGB , 
    (SUM(a.total_pages) - SUM(a.used_pages)) * 8 / 1024 / 1024 AS UnusedSpaceGB
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 = 'YourTable'
    AND t.is_ms_shipped = 0
    AND i.OBJECT_ID > 255 
GROUP BY 
    t.Name, s.Name, p.Rows
ORDER BY 
    UsedSpaceGB DESC, t.Name
  • I'd add `CONVERT(DECIMAL,SUM(a.total_pages))` so it would display info for tables smaller than GB – Bogdan Mart Mar 11 '17 at 15:48
  • Something here is wrong. The query results in a size reported that is more than double what SSMS table properties show. – Vaelek Jun 22 '21 at 16:14
  • This produces incorrect results for tables containing Filtered indices. A filtered index contains a different row-count causing the group-by to produce multiple rows for the same table. I suggest the definition for column RowCounts should be MAX(p.rows) as RowCounts, and p.Rows removed from the GROUP BY ... p.Rows. – ripvlan Apr 08 '22 at 17:57
14

Do you by size mean the number of records in the table, by any chance? In that case:

SELECT COUNT(*) FROM your_table_name
mwittrock
  • 2,871
  • 1
  • 17
  • 20
9

I know that in SQL 2012 (may work in other versions) you can do the following:

  1. Right click on the database name in the Object Explorer.
  2. Select Reports > Standard Reports > Disk Usage by Top Tables.

That will give you a list of the top 1000 tables and then you can order it by data size etc.

Justin Clarke
  • 602
  • 7
  • 7
9

And in PostgreSQL:

SELECT pg_size_pretty(pg_relation_size('tablename'));
Frank Heikens
  • 117,544
  • 24
  • 142
  • 135
  • btw, to see results from deletions with this query, you probably need to vacuum. Here's a query to see all public tables at once: `SELECT table_name, pg_size_pretty(pg_relation_size(table_names.table_name)) AS size from (select table_name from information_schema.tables where table_schema = 'public') AS table_names ORDER BY pg_relation_size(table_names.table_name) DESC;` – Noumenon Apr 25 '17 at 16:50
6

SQL Server, nicely formatted table for all tables in KB/MB:

SELECT 
    t.NAME AS TableName,
    s.Name AS SchemaName,
    p.rows AS RowCounts,
    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 
    t.Name
Kairan
  • 5,342
  • 27
  • 65
  • 104
2

You may refer the answer by Marc_s in another thread, Very useful.

Get size of all tables in database

Community
  • 1
  • 1
BMG
  • 489
  • 6
  • 9
2

Here's a simple query, if you are just trying to find the largest tables.

  -- Find largest table partitions
 SELECT top 20 obj.name, LTRIM (STR ( sz.in_row_data_page_count * 8, 15, 0) + ' KB') as Size, * FROM sys.dm_db_partition_stats sz
inner join sys.objects obj on obj.object_id = sz.object_id
  order by sz.in_row_data_page_count desc
  • 2
    Welcome to Stack Overflow! Although this code may help to solve the problem, it doesn't explain _why_ and/or _how_ it answers the question. Providing this additional context would significantly improve its long-term educational value. Please [edit] your answer to add explanation, including what limitations and assumptions apply. I know it's a poor question - that's even more reason to be clear in the reply. – Toby Speight Oct 03 '16 at 15:59
1

In SQL Server run below query you will get table with size of table.

SELECT 
   CASE WHEN (GROUPING(sob.name)=1) THEN 'All_Tables'
   ELSE ISNULL(sob.name, 'unknown') END AS TableName,
   SUM(sys.length) AS ByteLength
FROM sysobjects sob, syscolumns sys
WHERE sob.xtype='u' AND sys.id = sob.id
GROUP BY sob.name
WITH CUBE
ORDER BY SUM(sys.length) DESC

Find Byte Size of All the Tables in Database

Sender
  • 6,660
  • 12
  • 47
  • 66