简体   繁体   中英

Postgres row_number() doubling table size roughly every 24 hours

I have an Assets table with ~165,000 rows in it. However, the Assets make up "Collections" and each Collection may have ~10,000 items, which I want to save a "rank" for so users can see where a given asset ranks within the collection.

The rank can change (based on an internal score), so it needs to be updated periodically (a few times an hour).

That's currently being done on a per-collection basis with this:

UPDATE assets a
SET rank = a2.seqnum
FROM
  (SELECT a2.*,
          row_number() OVER (
                             ORDER BY elo_rating DESC) AS seqnum
   FROM assets a2
   WHERE a2.collection_id = #{collection_id} ) a2
WHERE a2.id = a.id;

However, that's causing the size of the table to double (ie 1GB to 2GB) roughly every 24 hours.

A VACUUM FULL clears this up, but that doesn't feel like a real solution.

Can the query be adjusted to not create so much (what I assume is) temporary storage?

Running PostgreSQL 13.

Every update writes a new row version in Postgres. So (aside from TOASTed columns) updating every row in the table doubles its size. That what you observe. Dead tuples can later be cleaned up to shrink the physical size of the table - that's what VACUUM FULL does, expensively.

Alternatively, you might just not run VACUUM FULL and keep the table at ~ twice it's minimal physical size. If you run plain VACUUM (without FULL !) enough - and if you don't have long running transactions blocking that - Postgres will have marked dead tuples in the free-space map by the time the next UPDATE kicks in and can reuse the disk space, thus staying at ~ twice its minimal size. That's a lot cheaper than shrinking and re-growing the table al the time, as the most expensive part is typically to physically grow the table.

Probably better yet, break out the ranking into a minimal separate 1:1 table, so that only minimal rows have to be written "a few times an hour".

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM