This is the view that you need to check:

select n_live_tup, n_dead_tup, relname from pg_stat_all_tables;  
Answer from Frank N Stein on Stack Overflow
๐ŸŒ
DEV Community
dev.to โ€บ sandeepkumardev โ€บ how-to-handle-dead-tuples-in-postgresql-54m1
Dead Tuples in PostgreSQL. - DEV Community
September 4, 2022 - If a table have some unique constraint and a user trying to Insert the same data again, PostgreSQL will return an error > Uniqueness violation. duplicate key value violates unique constraint. We can avoid this by using ON CONFLICT DO NOTHING clause. INSERT INTO users VALUES ('name', 'email@gmail.com') ON CONFLICT DO NOTHING; It'll return INSERT 0 0 indicates that nothing was inserted in the table, the query didn't error out. In the case of ON CONFLICT DO NOTHING no dead tuples are generated because of the pre-check.
Discussions

Custom Alert - Dead tuples percentage - pg_stat_user_tables
Description In PostgreSQL, an UPDATE or DELETE of a row does not immediately remove the old version of the row. This approach is necessary to gain the benefits of multi-version concurrency control (MVCC) - the row version must not be deleted while it is still potentially visible to other ... More on thwack.solarwinds.com
๐ŸŒ thwack.solarwinds.com
August 3, 2020
sql - How to find dead tuples (fragmentation) in PostgreSQL 8.2 ( for Greenplum)? - Stack Overflow
I know, how to find dead tuples in the new version of PostgreSQL. I have already shared two article on this. PostgreSQL: How to check Table Fragmentation using pgstattuple module More on stackoverflow.com
๐ŸŒ stackoverflow.com
postgresql - POSTGRES: How do I understand the real number of dead tuples in a given table - Stack Overflow
I have a database transactions: Table "public.transaction" Column | Type | Collation | Nullable | ... More on stackoverflow.com
๐ŸŒ stackoverflow.com
How many rows can fit in a Postgres table?
A page is an 8K block of memory. 4,294,967,295 pages ~= 32 terabytes. According to that statement, a table can be up to 32 terabytes in size. So it depends on how big your rows are. I assume that that number also includes unvacuumed dead tuples, since they also take up space on those pages. So it also depends how well vacuumed it is. In the worst case you would run out of space with 0 rows. But okay what's the best case? Say you have no dead tuples and all of your rows are just boolean (which are 1 byte). This isn't a very useful table but we're just seeing how many rows we can fit. Each page is 8192 bytes. 24 bytes go to the page header. Each row has a 23 byte header. The boolean data is 1 byte, so 24 bytes per row. (8192 - 24) / 24 = 340.3. So you could fit 340 1-byte tuples, max, in a page. 340 rows per page * 4294967295 pages= 1,460,288,880,300 rows. A bit less than 1.5 trillion rows. More on reddit.com
๐ŸŒ r/PostgreSQL
12
10
August 22, 2022
๐ŸŒ
Codecademy
codecademy.com โ€บ learn โ€บ fscp-22-advanced-postgresql โ€บ modules โ€บ wdcp-22-database-maintenence โ€บ cheatsheet
Advanced PostgreSQL: Database Maintenence Cheatsheet | Codecademy
Dead tuples are not referenced ... displayed to the DB user: You can check the number of dead tuples with the internal PostgreSQL statistic tables....
๐ŸŒ
Substack
skylinecodes.substack.com โ€บ postgresql dead tuples: mvcc, autovacuum, and database bloat
PostgreSQL Dead Tuples: MVCC, Autovacuum, and Database Bloat
May 3, 2025 - This returns the total table size, number of live vs. dead tuples, and bytes wasted on dead tuples. Seeing a high dead_tuple_count or large dead_tuple_len percentage is a red flag. You can also inspect the autovacuum log activity. In postgresql.conf, set for example: log_autovacuum_min_duration = 0 # log all autovacuum runs ยท Then check the logs: each autovacuum report will include how many tuples were removed from each tableโ€‹. Together, these tools let you track which tables are building up dead tuples and whether autovacuum is keeping up.
๐ŸŒ
PostgreSQL
postgresql.org โ€บ docs โ€บ 9.1 โ€บ pgstattuple.html
PostgreSQL: Documentation: 9.1: pgstattuple
October 27, 2016 - pgstattuple judges a tuple is "dead" if HeapTupleSatisfiesNow returns false.
๐ŸŒ
Shubhamdipt
shubhamdipt.com โ€บ blog โ€บ how-to-clean-dead-tuples-and-monitor-postgresql-using-vacuum
How to clean dead tuples and monitor PostgreSQL (using VACUUM)
The ANALYZE process with vacuum updates the statistics of all the tables. (autovacuum already does this process by default) postgres=# \c <database_name>; <database_name>=# VACUUM (VERBOSE, ANALYZE); Check ...
๐ŸŒ
Medium
medium.com โ€บ @nakulmitra2114 โ€บ postgresql-performance-optimization-cleaning-dead-tuples-reindexing-9b1346408b97
PostgreSQL Performance Optimization โ€” Cleaning Dead Tuples & Reindexing | by Nakul Mitra | Towards Dev
March 8, 2026 - PostgreSQL must scan through dead tuples to fetch valid data. Indexes grow larger, making queries slower. Tables and indexes become bloated, increasing storage requirements. We can check for dead tuples using the pg_stat_user_tables view:
๐ŸŒ
PostgreSQL
postgresql.org โ€บ docs โ€บ 9.6 โ€บ pgstattuple.html
PostgreSQL: Documentation: 9.6: pgstattuple
August 12, 2021 - Whereas pgstattuple always performs a full-table scan and returns an exact count of live and dead tuples (and their sizes) and free space, pgstattuple_approx tries to avoid the full-table scan and returns exact dead tuple statistics along with ...
Find elsewhere
๐ŸŒ
Medium
firattamur.medium.com โ€บ dead-tuples-in-focus-enhancing-postgresql-performance-94ebbd4b96c9
Dead Tuples In Focus โ€” Vol I: Enhancing PostgreSQL Performance ๐Ÿš€ | by firattamur | Medium
January 14, 2024 - Now, we can check the table using the following command: postgres=# \dt List of relations Schema | Name | Type | Owner --------+-------+-------+-------- public | users | table | postgres (1 row) In the intriguing universe of PostgreSQL, โ€˜dead tuplesโ€™ are a topic that often captivates database aficionados.
๐ŸŒ
Medium
firattamur.medium.com โ€บ dead-tuples-in-focus-vol-ii-enhancing-postgresql-performance-ce7d84f76082
Dead Tuples In Focus โ€” Vol II: Enhancing PostgreSQL Performance ๐Ÿš€ | by firattamur | Medium
January 14, 2024 - Following the similar steps outlined above, once we verify the count of dead tuples, we can proceed to run VACUUM FULL this time. VACUUM does shrink your database size! If you check dead tuples count again, you will see that it is 0 now. postgres=# SELECT relname, n_dead_tup FROM pg_stat_user_tables WHERE relname = 'users'; relname | n_dead_tup ---------+------------ users | 0 (1 row)
๐ŸŒ
Gold Lapel
goldlapel.com โ€บ home โ€บ glossary โ€บ postgresql concepts โ€บ dead tuple
Dead Tuples in PostgreSQL: What They Are and Why They Matter | Gold Lapel
March 21, 2026 - The fastest check. The n_dead_tup column reports an estimate of dead tuples per table, updated by autovacuum and ANALYZE. Compare it to n_live_tup to get a dead tuple ratio, and check last_autovacuum to see when cleanup last ran.
๐ŸŒ
SolarWinds
thwack.solarwinds.com โ€บ home โ€บ products โ€บ database performance analyzer (dpa)
Custom Alert - Dead tuples percentage - pg_stat_user_tables - THWACK
August 3, 2020 - Description In PostgreSQL, an UPDATE or DELETE of a row does not immediately remove the old version of the row. This approach is necessary to gain the benefits of multi-version concurrency control (MVCC) - the row version must not be deleted while it is still potentially visible to other transactions.
๐ŸŒ
Dbrnd
dbrnd.com โ€บ 2016 โ€บ 10 โ€บ postgresql-script-to-find-total-live-tuples-and-dead-tuples-row-of-a-table-execute-vacuum-remove-fragmentation-improve-performance
PostgreSQL: Script to find total Live Tuples and Dead Tuples (Row) of a Table
October 4, 2016 - Periodically, We should find dead rows of the object and we should remove it using VACUUM techniques of PostgreSQL. By this way, we can increase the overall performance of PostgreSQL Database Server. PostgreSQL: Short note on VACUUM, VACUUM FULL and ANALYZE ยท Find out Live Tuples or Dead Tuples using two different scripts.
๐ŸŒ
Fujitsu PostgreSQL
postgresql.fastware.com โ€บ pzone โ€บ 2025-03-improving-postgresql-efficiency-by-handling-dead-tuples
Improving PostgreSQL efficiency by handling dead tuples
December 30, 2025 - Automatic statistics collection: PostgreSQL automatically collects statistics but running ANALYZE manually can be beneficial after significant data changes. ... Adjust thresholds: Modify the autovacuum_vacuum_threshold and autovacuum_vacuum_scale_factor parameters to trigger VACUUM operations more frequently. This helps in keeping dead tuple accumulation in check...
๐ŸŒ
Wordpress
dbasid.wordpress.com โ€บ find-the-live-and-dead-tuple
Find the Live and Dead Tuple
April 19, 2018 - By this way, we can increase the ... to check the fragmentation level of Table.PostgreSQL provides pgstattuple module to get all tuples information of a Table....
Top answer
1 of 1
4

Don't use autovacuum. Greenplum isn't PostgreSQL and autovacuum does not work in the database. I highly recommend not tagging Greenplum posts with PostgreSQL because you will likely get incorrect information. It would be like posting a question about OSX and also tagging BSD.

Vacuum Heap tables with bloat:

psql -t -A -c "SELECT E'VACUUM \"' || bdinspname || E'\".\"' || bdirelname || E'\";' FROM gp_toolkit.gp_bloat_diag WHERE bdinspname <> 'pg_catalog'" | psql -e

But most all of your tables in Greenplum will likely not be heap based which uses MVCC and instead use "Append Optimized" or AO for short. It uses a visibility map to hide deleted rows and the files are smaller so it is faster. It also allows the table to be compressed and column oriented.

AO tables also need maintenance but unlike heap tables, it has a compaction threshold built in controlled by gp_appendonly_compaction_threshold GUC. Just VACUUM all AO tables and the database will automatically rebuild the table if the percentage of hidden rows exceeds 10%.

Greenplum still suffers from the freeze age problem that was inherited from PostgreSQL. This script typically won't return any rows but on older installations with tables that haven't been touched in a very long time, you might start to vacuum tables.

vacuum_freeze_min_age=$(psql -t -A -c "show vacuum_freeze_min_age;")
psql -t -A -c "SELECT E'VACUUM \"' || n.nspname || E'\".\"' || c.relname || E'\";' FROM pg_class c join pg_namespace n ON c.relnamespace = n.oid WHERE age(relfrozenxid) > $vacuum_freeze_min_age AND c.relkind = 'r'" | psql -e

While you are at it, you should schedule analyzedb to analyze all tables on a regular basis. Example:

analyzedb -d gpadmin -s tpcds

Don't forget the catalog!

psql -t -A -c "SELECT E'VACUUM ANALYZE \"' || n.nspname || E'\".\"' || c.relname || E'\";' FROM pg_class c JOIN pg_namespace n ON c.relnamespace = n.oid WHERE n.nspname = 'pg_catalog' AND c.relkind = 'r'" | psql -e

This reindexes the catalog indexes:

reindexdb -s
๐ŸŒ
CYBERTEC PostgreSQL
cybertec-postgresql.com โ€บ home โ€บ killed index tuples
Killed index tuples | a little known performance feature
March 5, 2024 - CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s. INFO: "pg_toast_16867": found 0 removable, 0 nonremovable row versions in 0 out of 0 pages DETAIL: 0 dead row versions cannot be removed yet, oldest xmin: 714 There were 0 unused item pointers. Skipped 0 pages due to buffer pins, 0 frozen pages. 0 pages are entirely empty. CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s. ... Those killed entries are considered live on a standby, potentially leading to weird performance differences between primary and standby clusters on particular select queries (https://www.postgresql.org/message-id/flat/7067.1529246768@sss.pgh.pa.us#d9e2e570ba34fc96c4300a362cbe8c38)
๐ŸŒ
DEV Community
dev.to โ€บ aws-heroes โ€บ dead-tuple-space-reused-without-vacuum-10fd
Postgres dead tuple space reused without vacuum - DEV Community
March 22, 2024 - This subtle change is visible in the dead column of the B-Tree leaf block which has been set to true by the previous read when it has found the dead tuple, so that the next reads don't have to do the same. postgres=# select substr(data,1,42), itemoffset, htid, itemlen, nulls, vars, dead from bt_page_items(get_raw_page('demo_pkey', 1)) order by data ; substr | itemoffset | htid | itemlen | nulls | vars | dead --------------------------------------------+------------+--------+---------+-------+------+------ 00 00 00 00 00 00 00 00 e0 07 00 00 78 78 | 2 | (0,1) | 520 | f | t | f 01 00 00 00 00 00