When using the RUM index distance operator (<=>) on PostgreSQL 17+ with high-frequency search terms (returning many matches), the query execution prematurely spills to disk (temp read/write buffers) even if work_mem is set high enough (e.g., 2GB) to easily fit the entire result set in RAM.
On PostgreSQL 15, the same query runs entirely in-memory with just 64MB of work_mem. On PostgreSQL 17/18, the query spills to disk, degrading performance significantly.
This is caused by a memory accounting bug in the PostgreSQL 17 compatibility code in rum_tuplesort_putrum() and rum_tuplesort_putrumitem(), where a custom RUM sort item pointer is incorrectly cast to a MinimalTuple to read the tuple length (t_len). On little-endian architectures, this reads the physical row Block Number and interprets it as an inflated tuple size (hundreds of megabytes), forcing tuplesort to exceed work_mem and spill immediately.
Environment:
PostgreSQL Version: 17.x, 18.x
RUM Version: 1.3.15 (upstream)
OS/Architecture: Linux (x86_64, little-endian)
When using the RUM index distance operator (<=>) on PostgreSQL 17+ with high-frequency search terms (returning many matches), the query execution prematurely spills to disk (temp read/write buffers) even if work_mem is set high enough (e.g., 2GB) to easily fit the entire result set in RAM.
On PostgreSQL 15, the same query runs entirely in-memory with just 64MB of work_mem. On PostgreSQL 17/18, the query spills to disk, degrading performance significantly.
This is caused by a memory accounting bug in the PostgreSQL 17 compatibility code in rum_tuplesort_putrum() and rum_tuplesort_putrumitem(), where a custom RUM sort item pointer is incorrectly cast to a MinimalTuple to read the tuple length (t_len). On little-endian architectures, this reads the physical row Block Number and interprets it as an inflated tuple size (hundreds of megabytes), forcing tuplesort to exceed work_mem and spill immediately.
Environment:
PostgreSQL Version: 17.x, 18.x
RUM Version: 1.3.15 (upstream)
OS/Architecture: Linux (x86_64, little-endian)