Skip to content

Commit 8253ad9

Browse files
committed
Add custom toaster for compression
Compressed rows are often large and get pushed to the toast relation in ~2KB chunks. Core writes each chunk with its own heap_insert() and index_insert() call. This change adds a custom toasting mechanism using relevant core function forks: chunks of a value are batched into a single heap_multi_insert() call instead, cutting the WAL and buffer-lock overhead. The forked functions live under tsl/src/import/, the existing home for code copied from PostgreSQL core, since compression_toast.c is exactly that. The new path is gated behind timescaledb.use_custom_toaster, off by default. Also add a TAP test confirming the WAL this change generates is correct.
1 parent d23634e commit 8253ad9

11 files changed

Lines changed: 841 additions & 8 deletions

File tree

.unreleased/pr_10388

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Implements: #10388 Add custom toaster for compression

src/guc.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ TSDLLEXPORT bool ts_guc_enable_direct_compress_auto_segmentby = true;
8585
int ts_guc_direct_compress_insert_tuple_sort_limit = 30000;
8686
TSDLLEXPORT int ts_guc_direct_compress_segmentby_min_rows = 5000;
8787
TSDLLEXPORT int ts_guc_direct_compress_segmentby_batch_size_limit = 500;
88+
TSDLLEXPORT bool ts_guc_use_custom_toaster = false;
8889
bool ts_guc_enable_deprecation_warnings = true;
8990
TSDLLEXPORT bool ts_guc_enable_optimizations = true;
9091
bool ts_guc_restoring = false;
@@ -631,6 +632,17 @@ _guc_init(void)
631632
NULL,
632633
NULL);
633634

635+
DefineCustomBoolVariable(MAKE_EXTOPTION("use_custom_toaster"),
636+
"Use a custom TOAST writer for compressed row inserts",
637+
"This setting is only used for compression.",
638+
&ts_guc_use_custom_toaster,
639+
false,
640+
PGC_USERSET,
641+
0,
642+
NULL,
643+
NULL,
644+
NULL);
645+
634646
DefineCustomIntVariable(MAKE_EXTOPTION("direct_compress_insert_tuple_sort_limit"),
635647
"Number of tuples that can be sorted at once in an INSERT operation",
636648
"This is mainly used to keep the memory footprint down for "

src/guc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ extern TSDLLEXPORT bool ts_guc_enable_direct_compress_auto_segmentby;
5353
extern int ts_guc_direct_compress_insert_tuple_sort_limit;
5454
extern TSDLLEXPORT int ts_guc_direct_compress_segmentby_min_rows;
5555
extern TSDLLEXPORT int ts_guc_direct_compress_segmentby_batch_size_limit;
56+
extern TSDLLEXPORT bool ts_guc_use_custom_toaster;
5657
extern TSDLLEXPORT bool ts_guc_enable_compressed_direct_batch_delete;
5758
extern TSDLLEXPORT int ts_guc_max_tuples_decompressed_per_dml;
5859
extern TSDLLEXPORT bool ts_guc_enable_compression_wal_markers;

tsl/src/compression/compression.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <access/attmap.h>
88
#include <access/attnum.h>
99
#include <access/detoast.h>
10+
#include <access/heapam.h>
1011
#include <access/htup_details.h>
1112
#include <access/skey.h>
1213
#include <access/tupdesc.h>
@@ -48,6 +49,7 @@
4849
#include "debug_assert.h"
4950
#include "debug_point.h"
5051
#include "guc.h"
52+
#include "import/compression_toast.h"
5153
#include "nodes/modify_hypertable.h"
5254
#include "ts_catalog/array_utils.h"
5355
#include "ts_catalog/catalog.h"
@@ -1778,11 +1780,18 @@ row_compressor_flush(RowCompressor *row_compressor, BulkWriter *writer, bool cha
17781780
}
17791781

17801782
Assert(writer->bistate != NULL);
1781-
heap_insert(writer->out_rel,
1782-
compressed_tuple,
1783-
writer->mycid,
1784-
writer->insert_options /*=options*/,
1785-
writer->bistate);
1783+
if (ts_guc_use_custom_toaster)
1784+
{
1785+
compression_heap_insert(writer, compressed_tuple);
1786+
}
1787+
else
1788+
{
1789+
heap_insert(writer->out_rel,
1790+
compressed_tuple,
1791+
writer->mycid,
1792+
writer->insert_options,
1793+
writer->bistate);
1794+
}
17861795
if (writer->indexstate->ri_NumIndices > 0)
17871796
{
17881797
ts_catalog_index_insert(writer->indexstate, compressed_tuple);
@@ -2015,6 +2024,7 @@ bulk_writer_close(BulkWriter *writer)
20152024
{
20162025
CatalogCloseIndexes(writer->indexstate);
20172026
}
2027+
compression_toast_writer_close(writer);
20182028
FreeExecutorState(writer->estate);
20192029
}
20202030

tsl/src/compression/compression.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,16 @@ typedef struct BulkWriter
155155
CommandId mycid;
156156
BulkInsertState bistate;
157157
int insert_options; /* heap insert options */
158+
/*
159+
* Toast relation/indexes for compression_toast_save_datum_multi(),
160+
* opened lazily on first use and closed by
161+
* compression_toast_writer_close(). NULL/0 if never toasted.
162+
*/
163+
Relation toast_rel;
164+
Relation *toast_indexes;
165+
int num_toast_indexes;
166+
int toast_valid_index;
167+
BulkInsertState toast_bistate;
158168
} BulkWriter;
159169

160170
typedef struct RowDecompressor

tsl/src/import/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
set(SOURCES)
1+
set(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/compression_toast.c)
22

33
if(USE_UMASH)
44
list(APPEND SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/umash.c)

0 commit comments

Comments
 (0)