Postgresql

How do you find the disk size of a Postgres PostgreSQL table and its indexes

19 September 2026 · 11 min read

How do you find the disk size of a Postgres  PostgreSQL table and its indexes

Understanding database performance is crucial for any application relying on data storage, and a significant aspect of this is knowing how to find the disk size of a Postgres / PostgreSQL table and its indexes. As databases grow, tables and their associated indexes can consume a considerable amount of storage space. Monitoring this usage allows database administrators and developers to identify potential bottlenecks, optimize query performance, and proactively plan for capacity upgrades. This article provides a comprehensive guide on how to efficiently determine the space occupied by your tables and indexes within a PostgreSQL database, ensuring you can manage your resources effectively and maintain a healthy, responsive system. We will explore various SQL queries and techniques to extract this information, empowering you with the knowledge to make informed decisions about database optimization and resource allocation.

Understanding Table and Index Size in PostgreSQL

PostgreSQL offers several built-in functions and system catalogs that provide insights into database object sizes. These tools allow you to query the database and retrieve information about the physical space occupied by tables, indexes, and other database components. Properly understanding how to utilize these functions can greatly assist in database administration, performance tuning, and capacity planning. Knowing the size of your tables and indexes allows you to make informed decisions about partitioning strategies, index optimization, and overall database design. Furthermore, this knowledge is invaluable for troubleshooting performance issues, as large tables or inefficient indexes can often be the root cause of slow queries.

Several factors influence the disk space used by a table or index. Data types, the number of rows, and the presence of indexes all contribute to the overall size. Data types like TEXT and JSONB can consume significant storage, especially if they contain large amounts of data. As the number of rows in a table increases, so does the disk space required to store the data. Indexes, while improving query performance, also require storage space, and poorly designed indexes can lead to excessive storage consumption. Therefore, understanding these factors and how they relate to the reported size is critical for effective database management. Monitoring these aspects helps ensure optimal performance and efficient resource utilization.

Regularly monitoring the size of tables and indexes is a best practice for database administration. This proactive approach allows you to identify trends, detect anomalies, and take corrective actions before performance is negatively impacted. For example, a sudden increase in table size might indicate a data ingestion issue or a need for data archiving. Similarly, an oversized index might suggest that the index is not being used effectively or that it needs to be rebuilt with different parameters. By incorporating size monitoring into your routine maintenance tasks, you can ensure the long-term health and efficiency of your PostgreSQL database.

Methods to Determine Table Size

PostgreSQL provides several SQL functions to determine the size of a table. These functions offer varying levels of detail, allowing you to retrieve the total size, the size of the table data, and the size of associated indexes. Here are some of the most commonly used functions:

  • pg_size_pretty(pg_relation_size(’table_name’)): Returns the size of the table data only in a human-readable format (e.g., ‘256 MB’).
  • pg_size_pretty(pg_total_relation_size(’table_name’)): Returns the total size of the table, including indexes and TOAST data, in a human-readable format. This is the most commonly used function.
  • pg_relation_size(’table_name’): Returns the size of the table data in bytes.
  • pg_total_relation_size(’table_name’): Returns the total size of the table, including indexes and TOAST data, in bytes.

The pg_size_pretty function is particularly useful because it formats the size in a human-readable format, making it easier to interpret the results. For example, instead of seeing a size in bytes, you’ll see it displayed as “10 GB” or “500 MB.” The pg_total_relation_size function provides the most comprehensive view of the table’s storage footprint, as it includes the size of the table data, indexes, and any associated TOAST data (data exceeding the standard row size limit). Using these functions, you can quickly and easily determine the disk space occupied by your tables.

For example, to find the total size of a table named users, you would use the following query:

SELECT pg_size_pretty(pg_total_relation_size('users'));

This query will return the total size of the users table, including its indexes, in a human-readable format. This simple query can be a powerful tool for monitoring and managing your database’s storage usage. Regularly running this query for critical tables can help you identify potential storage issues before they impact performance. As PostgreSQL evolves, these functions remain a reliable and accurate way to assess table sizes. Understanding the differences between these functions allows for precise monitoring and efficient management of PostgreSQL database storage. Learn more about database optimization techniques.

Finding Index Size in PostgreSQL

Indexes are essential for improving query performance, but they also consume disk space. It’s important to monitor the size of your indexes to ensure they are not unnecessarily large or inefficient. PostgreSQL provides functions to determine the size of individual indexes or all indexes associated with a table.

Here are the key functions and techniques to find index sizes:

  • pg_size_pretty(pg_indexes_size(’table_name’)): Returns the total size of all indexes associated with a given table in a human-readable format.
  • pg_indexes_size(’table_name’): Returns the total size of all indexes associated with a given table in bytes.
  • pg_size_pretty(pg_relation_size(‘index_name’)): Returns the size of a specific index in a human-readable format.

To find the total size of all indexes for a table named orders, you can use the following query:

SELECT pg_size_pretty(pg_indexes_size('orders'));

This query will return the combined size of all indexes on the orders table. To find the size of a specific index, such as an index named idx_order_date, you can use the following query:

SELECT pg_size_pretty(pg_relation_size('idx_order_date'));

This query will return the size of the idx_order_date index. Regularly monitoring index sizes can help you identify opportunities for index optimization. For instance, if an index is significantly larger than the table it indexes, it might indicate that the index is not being used effectively or that it needs to be rebuilt with different parameters. “Index bloat is a common issue, and monitoring index size helps identify and address it,” according to a PostgreSQL performance tuning guide from Cybertec PostgreSQL [^1^]. By carefully managing your indexes, you can ensure optimal query performance and efficient use of disk space.

Combining Table and Index Size Information

To get a complete picture of storage usage, it’s often helpful to combine the table size and index size information. You can use SQL queries to retrieve both values and present them in a single result set. This combined view provides a clear understanding of the total storage footprint of a table, including its data and indexes. This approach is particularly useful for identifying tables that are consuming a disproportionate amount of storage.

Here’s an example query that combines table and index size information:

SELECT 'users' AS table_name, pg_size_pretty(pg_relation_size('users')) AS table_size, pg_size_pretty(pg_indexes_size('users')) AS index_size, pg_size_pretty(pg_total_relation_size('users')) AS total_size; 

This query will return a single row with the table name, table size, index size, and total size for the users table. You can modify this query to include multiple tables or to retrieve this information for all tables in your database. To do this, you can use the pg_tables system catalog to iterate over all tables and retrieve their sizes. A more advanced query using pg_tables can provide a comprehensive overview of storage usage across your entire database, enabling you to identify the largest tables and indexes and prioritize optimization efforts. Analyzing this data can reveal areas where you can reclaim disk space or improve query performance by optimizing indexes. This combined view allows for strategic allocation of resources.

Featured Snippet:
To find the total size of a table including its indexes in PostgreSQL, use the pg_total_relation_size function. This function returns the size in bytes. To format the size in a human-readable format (e.g., “10 GB”), wrap the pg_total_relation_size function with pg_size_pretty. For example: SELECT pg_size_pretty(pg_total_relation_size(‘your_table_name’)); This will provide the total disk space occupied by the table and its associated indexes.

Practical Steps and Considerations

Now that you understand how to retrieve table and index sizes, let’s outline some practical steps and considerations for using this information effectively. Regular monitoring of table and index sizes is crucial for maintaining database performance and managing storage resources. Implement a routine monitoring process to track the growth of your tables and indexes over time. This will help you identify potential storage bottlenecks and proactively address them before they impact performance. You should also consider automating this process using scripting or monitoring tools to ensure consistent and timely data collection.

Here’s a simple process to follow for monitoring table and index sizes:

  1. Identify critical tables and indexes that require monitoring.
  2. Create SQL queries to retrieve the size information for these objects.
  3. Schedule these queries to run regularly (e.g., daily or weekly).
  4. Store the results in a log file or database table for historical analysis.
  5. Analyze the data to identify trends and anomalies.
  6. Take corrective actions as needed (e.g., optimize indexes, archive data).

When analyzing table and index sizes, consider the following factors: Data growth rate, index effectiveness, and hardware limitations. A rapid increase in table size might indicate a need for data archiving or partitioning. Large indexes that are not being used effectively can be dropped or rebuilt with different parameters. Finally, be mindful of your hardware limitations and plan for capacity upgrades as needed. By carefully considering these factors, you can ensure that your PostgreSQL database remains performant and efficient over time. [^2^] Remember to consult the official PostgreSQL documentation for the most up-to-date information on these functions and techniques. Also, consider using tools like pgAdmin for visual monitoring of disk usage.

Infographic here - Visual representation of the table and index size monitoring process.
FAQ: Table and Index Sizes in PostgreSQL ----------------------------------------
How often should I check my PostgreSQL table and index sizes?
The frequency depends on the rate of data change. For actively updated tables, checking daily or weekly is recommended. For relatively static tables, monthly checks may suffice.
What if I find an unexpectedly large table or index?
Investigate the cause. It could be due to data growth, inefficient indexing, or data bloat. Consider archiving old data, optimizing indexes, or running VACUUM FULL (with caution). \[^3^\]
Does VACUUM FULL reduce the size of my tables and indexes?
VACUUM FULL rewrites the entire table, reclaiming disk space. However, it requires exclusive access and can be disruptive. Consider using VACUUM and ANALYZE more frequently as a less disruptive alternative.
Can I automate the process of monitoring table and index sizes?
Yes, you can use scripting languages like Python or shell scripting to automate the execution of SQL queries and store the results for analysis. There are also database monitoring tools that provide built-in support for tracking table and index sizes.
By understanding how to find the disk size of a Postgres / PostgreSQL table and its indexes, you're equipped to proactively manage your database resources. We've explored SQL queries, practical steps, and key considerations for effectively monitoring storage usage. We’ve also touched on automation and troubleshooting common issues. This knowledge enables you to optimize query performance, plan for capacity upgrades, and ensure the long-term health of your PostgreSQL database.

Now, take this knowledge and apply it to your own PostgreSQL databases. Start by running the queries we discussed on your critical tables and indexes. Analyze the results and identify any potential areas for optimization. By taking these proactive steps, you can ensure that your database remains performant, efficient, and well-managed. Consider exploring related topics such as index optimization, data partitioning, and database performance tuning to further enhance your skills.

[^1^]: Cybertec PostgreSQL Performance Tuning Guide: [https://www.cybertec-postgresql. Question & Answer :

I’m coming to Postgres from Oracle and looking for a way to find the table and index size in terms of bytes/MB/GB/etc, or even better the size for all tables. In Oracle I had a nasty long query that looked at user_lobs and user_segments to give back an answer.

I assume in Postgres there’s something I can use in the information_schema tables, but I’m not seeing where.

Try the Database Object Size Functions. An example:

SELECT pg_size_pretty(pg_total_relation_size('"<schema>"."<table>"')); 

For all tables, something along the lines of:

SELECT table_schema || '.' || table_name AS table_full_name, pg_size_pretty(pg_total_relation_size('"' || table_schema || '"."' || table_name || '"')) AS size FROM information_schema.tables ORDER BY pg_total_relation_size('"' || table_schema || '"."' || table_name || '"') DESC; 

Edit: Here’s the query submitted by @phord, for convenience:

SELECT table_name, pg_size_pretty(table_size) AS table_size, pg_size_pretty(indexes_size) AS indexes_size, pg_size_pretty(total_size) AS total_size FROM ( SELECT table_name, pg_table_size(table_name) AS table_size, pg_indexes_size(table_name) AS indexes_size, pg_total_relation_size(table_name) AS total_size FROM ( SELECT ('"' || table_schema || '"."' || table_name || '"') AS table_name FROM information_schema.tables ) AS all_tables ORDER BY total_size DESC ) AS pretty_sizes; 

I’ve modified it slightly to use pg_table_size() to include metadata and make the sizes add up.