Skip to content

Commit 3c74de1

Browse files
committed
Add compression tuple filtering information to EXPLAIN
Show information about filtered batches to EXPLAIN ANALYZE output.
1 parent 47efc2f commit 3c74de1

File tree

8 files changed

+44
-21
lines changed

8 files changed

+44
-21
lines changed

src/nodes/chunk_dispatch/chunk_dispatch.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ typedef struct ChunkDispatchState
7474
ResultRelInfo *rri;
7575
/* flag to represent dropped attributes */
7676
bool is_dropped_attr_exists;
77+
int64 batches_filtered;
7778
int64 batches_decompressed;
7879
int64 tuples_decompressed;
7980

src/nodes/hypertable_modify.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,10 +240,13 @@ hypertable_modify_explain(CustomScanState *node, List *ancestors, ExplainState *
240240
foreach (lc, chunk_dispatch_states)
241241
{
242242
ChunkDispatchState *cds = (ChunkDispatchState *) lfirst(lc);
243+
state->batches_filtered += cds->batches_filtered;
243244
state->batches_decompressed += cds->batches_decompressed;
244245
state->tuples_decompressed += cds->tuples_decompressed;
245246
}
246247
}
248+
if (state->batches_filtered > 0)
249+
ExplainPropertyInteger("Batches filtered", NULL, state->batches_filtered, es);
247250
if (state->batches_decompressed > 0)
248251
ExplainPropertyInteger("Batches decompressed", NULL, state->batches_decompressed, es);
249252
if (state->tuples_decompressed > 0)

src/nodes/hypertable_modify.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ typedef struct HypertableModifyPath
1717
CustomPath cpath;
1818
} HypertableModifyPath;
1919

20+
/*
21+
* State for the hypertable_modify custom scan node.
22+
*
23+
* This struct definition is also used in ts_stat_statements, so any new fields
24+
* should only be added at the end of the struct.
25+
*/
2026
typedef struct HypertableModifyState
2127
{
2228
CustomScanState cscan_state;
@@ -25,6 +31,7 @@ typedef struct HypertableModifyState
2531
Snapshot snapshot;
2632
int64 tuples_decompressed;
2733
int64 batches_decompressed;
34+
int64 batches_filtered;
2835
} HypertableModifyState;
2936

3037
extern void ts_hypertable_modify_fixup_tlist(Plan *plan);

tsl/src/compression/compression.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,7 @@ const CompressionAlgorithmDefinition *algorithm_definition(CompressionAlgorithm
410410

411411
struct decompress_batches_stats
412412
{
413+
int64 batches_filtered;
413414
int64 batches_decompressed;
414415
int64 tuples_decompressed;
415416
};

tsl/src/compression/compression_dml.c

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ decompress_batches_for_insert(const ChunkInsertState *cis, TupleTableSlot *slot)
203203
cis->cds->skip_current_tuple = true;
204204
}
205205

206+
cis->cds->batches_filtered += stats.batches_filtered;
206207
cis->cds->batches_decompressed += stats.batches_decompressed;
207208
cis->cds->tuples_decompressed += stats.tuples_decompressed;
208209

@@ -328,6 +329,7 @@ decompress_batches_for_update_delete(HypertableModifyState *ht_state, Chunk *chu
328329
filter = lfirst(lc);
329330
pfree(filter);
330331
}
332+
ht_state->batches_filtered += stats.batches_filtered;
331333
ht_state->batches_decompressed += stats.batches_decompressed;
332334
ht_state->tuples_decompressed += stats.tuples_decompressed;
333335

@@ -358,10 +360,7 @@ decompress_batches_indexscan(Relation in_rel, Relation out_rel, Relation index_r
358360
int num_segmentby_filtered_rows = 0;
359361
int num_heap_filtered_rows = 0;
360362

361-
struct decompress_batches_stats stats = {
362-
.batches_decompressed = 0,
363-
.tuples_decompressed = 0,
364-
};
363+
struct decompress_batches_stats stats = { 0 };
365364

366365
/* TODO: Optimization by reusing the index scan while working on a single chunk */
367366
IndexScanDesc scan = index_beginscan(in_rel, index_rel, snapshot, num_index_scankeys, 0);
@@ -442,6 +441,7 @@ decompress_batches_indexscan(Relation in_rel, Relation out_rel, Relation index_r
442441
skip_current_tuple))
443442
{
444443
row_decompressor_reset(&decompressor);
444+
stats.batches_filtered++;
445445
continue;
446446
}
447447

@@ -524,10 +524,7 @@ decompress_batches_seqscan(Relation in_rel, Relation out_rel, Snapshot snapshot,
524524
TableScanDesc scan = table_beginscan(in_rel, snapshot, num_scankeys, scankeys);
525525
int num_scanned_rows = 0;
526526
int num_filtered_rows = 0;
527-
struct decompress_batches_stats stats = {
528-
.batches_decompressed = 0,
529-
.tuples_decompressed = 0,
530-
};
527+
struct decompress_batches_stats stats = { 0 };
531528

532529
while (table_scan_getnextslot(scan, ForwardScanDirection, slot))
533530
{
@@ -586,6 +583,7 @@ decompress_batches_seqscan(Relation in_rel, Relation out_rel, Snapshot snapshot,
586583
skip_current_tuple))
587584
{
588585
row_decompressor_reset(&decompressor);
586+
stats.batches_filtered++;
589587
continue;
590588
}
591589

tsl/test/shared/expected/compress_unique_index.out

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,11 @@ ERROR: duplicate key value violates unique constraint "_hyper_X_X_chunk_uniq_ex
2727
EXPLAIN (analyze,costs off,summary off,timing off) INSERT INTO compress_unique VALUES ('2000-01-01','m1','c2','2000-01-02');
2828
QUERY PLAN
2929
Custom Scan (HypertableModify) (actual rows=0 loops=1)
30+
Batches filtered: 1
3031
-> Insert on compress_unique (actual rows=0 loops=1)
3132
-> Custom Scan (ChunkDispatch) (actual rows=1 loops=1)
3233
-> Result (actual rows=1 loops=1)
33-
(4 rows)
34+
(5 rows)
3435

3536
-- should decompress no batches
3637
EXPLAIN (analyze,costs off,summary off,timing off) INSERT INTO compress_unique VALUES ('2000-01-01','m1','c3','2000-01-02');

tsl/test/shared/expected/compression_dml.out

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -260,27 +260,30 @@ QUERY PLAN
260260
BEGIN; :ANALYZE UPDATE lazy_decompress SET value = 3.14 WHERE value = 0; ROLLBACK;
261261
QUERY PLAN
262262
Custom Scan (HypertableModify) (actual rows=0 loops=1)
263+
Batches filtered: 6
263264
-> Update on lazy_decompress (actual rows=0 loops=1)
264265
Update on _hyper_X_X_chunk lazy_decompress_1
265266
-> Result (actual rows=0 loops=1)
266267
-> Seq Scan on _hyper_X_X_chunk lazy_decompress_1 (actual rows=0 loops=1)
267268
Filter: (value = '0'::double precision)
268-
(6 rows)
269+
(7 rows)
269270

270271
BEGIN; :ANALYZE UPDATE lazy_decompress SET value = 3.14 WHERE value = 0 AND device='d1'; ROLLBACK;
271272
QUERY PLAN
272273
Custom Scan (HypertableModify) (actual rows=0 loops=1)
274+
Batches filtered: 6
273275
-> Update on lazy_decompress (actual rows=0 loops=1)
274276
Update on _hyper_X_X_chunk lazy_decompress_1
275277
-> Result (actual rows=0 loops=1)
276278
-> Seq Scan on _hyper_X_X_chunk lazy_decompress_1 (actual rows=0 loops=1)
277279
Filter: ((value = '0'::double precision) AND (device = 'd1'::text))
278-
(6 rows)
280+
(7 rows)
279281

280282
-- 1 batch decompression
281283
BEGIN; :ANALYZE UPDATE lazy_decompress SET value = 3.14 WHERE value = 2300; ROLLBACK;
282284
QUERY PLAN
283285
Custom Scan (HypertableModify) (actual rows=0 loops=1)
286+
Batches filtered: 5
284287
Batches decompressed: 1
285288
Tuples decompressed: 1000
286289
-> Update on lazy_decompress (actual rows=0 loops=1)
@@ -289,11 +292,12 @@ QUERY PLAN
289292
-> Seq Scan on _hyper_X_X_chunk lazy_decompress_1 (actual rows=1 loops=1)
290293
Filter: (value = '2300'::double precision)
291294
Rows Removed by Filter: 999
292-
(9 rows)
295+
(10 rows)
293296

294297
BEGIN; :ANALYZE UPDATE lazy_decompress SET value = 3.14 WHERE value > 3100 AND value < 3200; ROLLBACK;
295298
QUERY PLAN
296299
Custom Scan (HypertableModify) (actual rows=0 loops=1)
300+
Batches filtered: 5
297301
Batches decompressed: 1
298302
Tuples decompressed: 1000
299303
-> Update on lazy_decompress (actual rows=0 loops=1)
@@ -302,11 +306,12 @@ QUERY PLAN
302306
-> Seq Scan on _hyper_X_X_chunk lazy_decompress_1 (actual rows=99 loops=1)
303307
Filter: ((value > '3100'::double precision) AND (value < '3200'::double precision))
304308
Rows Removed by Filter: 901
305-
(9 rows)
309+
(10 rows)
306310

307311
BEGIN; :ANALYZE UPDATE lazy_decompress SET value = 3.14 WHERE value BETWEEN 3100 AND 3200; ROLLBACK;
308312
QUERY PLAN
309313
Custom Scan (HypertableModify) (actual rows=0 loops=1)
314+
Batches filtered: 5
310315
Batches decompressed: 1
311316
Tuples decompressed: 1000
312317
-> Update on lazy_decompress (actual rows=0 loops=1)
@@ -315,7 +320,7 @@ QUERY PLAN
315320
-> Seq Scan on _hyper_X_X_chunk lazy_decompress_1 (actual rows=101 loops=1)
316321
Filter: ((value >= '3100'::double precision) AND (value <= '3200'::double precision))
317322
Rows Removed by Filter: 899
318-
(9 rows)
323+
(10 rows)
319324

320325
-- check GUC is working, should be 6 batches and 6000 tuples decompresed
321326
SET timescaledb.enable_dml_decompression_tuple_filtering TO off;
@@ -337,57 +342,62 @@ RESET timescaledb.enable_dml_decompression_tuple_filtering;
337342
BEGIN; :ANALYZE DELETE FROM lazy_decompress WHERE value = 0; ROLLBACK;
338343
QUERY PLAN
339344
Custom Scan (HypertableModify) (actual rows=0 loops=1)
345+
Batches filtered: 6
340346
-> Delete on lazy_decompress (actual rows=0 loops=1)
341347
Delete on _hyper_X_X_chunk lazy_decompress_1
342348
-> Seq Scan on _hyper_X_X_chunk lazy_decompress_1 (actual rows=0 loops=1)
343349
Filter: (value = '0'::double precision)
344-
(5 rows)
350+
(6 rows)
345351

346352
BEGIN; :ANALYZE DELETE FROM lazy_decompress WHERE value = 0 AND device='d1'; ROLLBACK;
347353
QUERY PLAN
348354
Custom Scan (HypertableModify) (actual rows=0 loops=1)
355+
Batches filtered: 6
349356
-> Delete on lazy_decompress (actual rows=0 loops=1)
350357
Delete on _hyper_X_X_chunk lazy_decompress_1
351358
-> Seq Scan on _hyper_X_X_chunk lazy_decompress_1 (actual rows=0 loops=1)
352359
Filter: ((value = '0'::double precision) AND (device = 'd1'::text))
353-
(5 rows)
360+
(6 rows)
354361

355362
-- 1 batch decompression
356363
BEGIN; :ANALYZE DELETE FROM lazy_decompress WHERE value = 2300; ROLLBACK;
357364
QUERY PLAN
358365
Custom Scan (HypertableModify) (actual rows=0 loops=1)
366+
Batches filtered: 5
359367
Batches decompressed: 1
360368
Tuples decompressed: 1000
361369
-> Delete on lazy_decompress (actual rows=0 loops=1)
362370
Delete on _hyper_X_X_chunk lazy_decompress_1
363371
-> Seq Scan on _hyper_X_X_chunk lazy_decompress_1 (actual rows=1 loops=1)
364372
Filter: (value = '2300'::double precision)
365373
Rows Removed by Filter: 999
366-
(8 rows)
374+
(9 rows)
367375

368376
BEGIN; :ANALYZE DELETE FROM lazy_decompress WHERE value > 3100 AND value < 3200; ROLLBACK;
369377
QUERY PLAN
370378
Custom Scan (HypertableModify) (actual rows=0 loops=1)
379+
Batches filtered: 5
371380
Batches decompressed: 1
372381
Tuples decompressed: 1000
373382
-> Delete on lazy_decompress (actual rows=0 loops=1)
374383
Delete on _hyper_X_X_chunk lazy_decompress_1
375384
-> Seq Scan on _hyper_X_X_chunk lazy_decompress_1 (actual rows=99 loops=1)
376385
Filter: ((value > '3100'::double precision) AND (value < '3200'::double precision))
377386
Rows Removed by Filter: 901
378-
(8 rows)
387+
(9 rows)
379388

380389
BEGIN; :ANALYZE DELETE FROM lazy_decompress WHERE value BETWEEN 3100 AND 3200; ROLLBACK;
381390
QUERY PLAN
382391
Custom Scan (HypertableModify) (actual rows=0 loops=1)
392+
Batches filtered: 5
383393
Batches decompressed: 1
384394
Tuples decompressed: 1000
385395
-> Delete on lazy_decompress (actual rows=0 loops=1)
386396
Delete on _hyper_X_X_chunk lazy_decompress_1
387397
-> Seq Scan on _hyper_X_X_chunk lazy_decompress_1 (actual rows=101 loops=1)
388398
Filter: ((value >= '3100'::double precision) AND (value <= '3200'::double precision))
389399
Rows Removed by Filter: 899
390-
(8 rows)
400+
(9 rows)
391401

392402
-- check GUC is working, should be 6 batches and 6000 tuples decompresed
393403
SET timescaledb.enable_dml_decompression_tuple_filtering TO off;

tsl/test/shared/expected/decompress_tracking.out

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,12 @@ QUERY PLAN
9494
BEGIN; :EXPLAIN_ANALYZE INSERT INTO decompress_tracking SELECT '2020-01-01 1:30','d1',random(); ROLLBACK;
9595
QUERY PLAN
9696
Custom Scan (HypertableModify) (actual rows=0 loops=1)
97+
Batches filtered: 1
9798
-> Insert on decompress_tracking (actual rows=0 loops=1)
9899
-> Custom Scan (ChunkDispatch) (actual rows=1 loops=1)
99100
-> Subquery Scan on "*SELECT*" (actual rows=1 loops=1)
100101
-> Result (actual rows=1 loops=1)
101-
(5 rows)
102+
(6 rows)
102103

103104
BEGIN; :EXPLAIN_ANALYZE INSERT INTO decompress_tracking SELECT '2020-01-01','d2',random(); ROLLBACK;
104105
QUERY PLAN
@@ -121,10 +122,11 @@ QUERY PLAN
121122
BEGIN; :EXPLAIN_ANALYZE INSERT INTO decompress_tracking (VALUES ('2020-01-01 1:30','d1',random()),('2020-01-01 1:30','d2',random())); ROLLBACK;
122123
QUERY PLAN
123124
Custom Scan (HypertableModify) (actual rows=0 loops=1)
125+
Batches filtered: 2
124126
-> Insert on decompress_tracking (actual rows=0 loops=1)
125127
-> Custom Scan (ChunkDispatch) (actual rows=2 loops=1)
126128
-> Values Scan on "*VALUES*" (actual rows=2 loops=1)
127-
(4 rows)
129+
(5 rows)
128130

129131
-- test prepared statements EXPLAIN still works after execution
130132
SET plan_cache_mode TO force_generic_plan;

0 commit comments

Comments
 (0)