SQL Server : Get size of all tables in database

T.Zacks 3,986 Reputation points
2021-07-11T08:28:44.977+00:00

The above sql works fine but i want the size in KB OR MB OR GB at the end i want a new column which show total size like TableSizeInMB+IndexSizeInMB KB OR MB OR GB

;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

thanks

Transact-SQL
Transact-SQL
A Microsoft extension to the ANSI SQL language that includes procedural programming, local variables, and various support functions.
4,560 questions
{count} votes

Accepted answer
  1. EchoLiu-MSFT 14,571 Reputation points
    2021-07-13T07:01:44.06+00:00

    Try:

      ;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  
      )  
      ,cte2 as(select  
          cte.TableName,   
          (cte.pages * 8.) as TableSizeInKB,   
          ((CASE WHEN cte.used_pages_count > cte.pages   
                      THEN cte.used_pages_count - cte.pages  
                      ELSE 0   
                END) * 8.) as IndexSizeInKB  
      from cte  
     )  
     select TableName,TableSizeInKB,IndexSizeInKB,  
     case when (TableSizeInKB+IndexSizeInKB)>1024*1024   
     then cast((TableSizeInKB+IndexSizeInKB)/1024*1024 as varchar)+'GB'  
     when (TableSizeInKB+IndexSizeInKB)>1024   
     then cast((TableSizeInKB+IndexSizeInKB)/1024 as varchar)+'MB'  
     else cast((TableSizeInKB+IndexSizeInKB) as varchar)+'KB' end [TableSizeIn+IndexSizeIn]  
     from cte2  
     order by 2 desc  
    

    114102-image.png

    2 people found this answer helpful.

2 additional answers

Sort by: Most helpful
  1. Viorel 112.9K Reputation points
    2021-07-11T20:22:37.78+00:00

    Maybe you want this formatting of total size:

    ;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
    ), 
    cte2 as
    (
    select
        cte.TableName, 
        cast((cte.pages * 8.) as decimal(10,3)) as TableSizeInKB, 
        cast(((CASE WHEN cte.used_pages_count > cte.pages 
                    THEN cte.used_pages_count - cte.pages
                    ELSE 0 
              END) * 8.) as decimal(10,3)) as IndexSizeInKB
    from cte
    )
    select TableName, TableSizeInKB, IndexSizeInKB,
        case 
           when s > 1024 * 1024 then format(s / 1024 / 1024, '0.###'' GB''')
           when s > 1024 then format(s / 1024, '0.###'' MB''')
           else format(s, '0.###'' KB''') end as [TableSize + IndexSize]
    from cte2
    cross apply (values (TableSizeInKB + IndexSizeInKB)) t(s)
    order by s desc
    
    1 person found this answer helpful.

  2. EchoLiu-MSFT 14,571 Reputation points
    2021-07-12T02:35:39.25+00:00

    Please also check:

     ;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
     )
     ,cte2 as(select
         cte.TableName, 
         cast((cte.pages * 8.) as decimal(10,3)) as TableSizeInKB, 
         cast(((CASE WHEN cte.used_pages_count > cte.pages 
                     THEN cte.used_pages_count - cte.pages
                     ELSE 0 
               END) * 8.) as decimal(10,3)) as IndexSizeInKB
     from cte
    )
    select TableName,TableSizeInKB,IndexSizeInKB,
    case when (TableSizeInKB+IndexSizeInKB)>1024*1024 
    then cast((TableSizeInKB+IndexSizeInKB)/1024*1024 as varchar)+'GB'
    when (TableSizeInKB+IndexSizeInKB)>1024 
    then cast((TableSizeInKB+IndexSizeInKB)/1024 as varchar)+'MB'
    else cast((TableSizeInKB+IndexSizeInKB) as varchar)+'KB' end [TableSizeIn+IndexSizeIn]
    from cte2
    order by 2 desc
    

    If you have any question, please feel free to let me know.

    Regards
    Echo


    If the answer is helpful, please click "Accept Answer" and upvote it.