Skip to content

Commit

Permalink
Correctly handle start of BitmapOr/BitmapAnd subplans
Browse files Browse the repository at this point in the history
  • Loading branch information
bonnefoa committed Apr 2, 2024
1 parent 2dfa049 commit 4e08652
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 12 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ OBJS = \
src/pg_tracing_span.o

REGRESSCHECKS = utility select extended insert trigger sample \
planstate parallel subxact full_buffer nested wal \
cleanup
planstate planstate_bitmap parallel subxact full_buffer \
nested wal cleanup
REGRESSCHECKS_OPTS = --no-locale --encoding=UTF8 --temp-config pg_tracing.conf

PGXS := $(shell $(PG_CONFIG) --pgxs)
Expand Down
57 changes: 57 additions & 0 deletions expected/planstate_bitmap.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*dddbs='postgres.db',traceparent='00-00000000000000000000000000000001-0000000000000001-01'*/ SELECT * from pg_tracing_test where a=1 OR a=2 OR a=3;
a | b
---+----------------------
1 | aaa
2 | aaa
3 | aaa
(3 rows)

SELECT span_operation, deparse_info, parameters, lvl from peek_ordered_spans where trace_id='00000000000000000000000000000001';
span_operation | deparse_info | parameters | lvl
-----------------------------------------------------------+-----------------------------------------------+------------------------+-----
SELECT * from pg_tracing_test where a=$1 OR a=$2 OR a=$3; | | $1 = 1, $2 = 2, $3 = 3 | 1
Planner | | | 2
ExecutorRun | | | 2
BitmapHeapScan on pg_tracing_test | Recheck Cond: ((a = 1) OR (a = 2) OR (a = 3)) | | 3
BitmapOr | | | 4
BitmapIndexScan on pg_tracing_index | Index Cond: (a = 1) | | 5
BitmapIndexScan on pg_tracing_index | Index Cond: (a = 2) | | 5
BitmapIndexScan on pg_tracing_index | Index Cond: (a = 3) | | 5
(8 rows)

--
-- +----------------------------------------------------------------------------------------------+
-- | A: BitmapOr |
-- ++-----------------------------+-------------------------------+-------------------------------+
-- |B: Bitmap Index Scan (aid=1) |C: Bitmap Index Scan (aid=2) |D: Bitmap Index Scan (aid=3) |
-- +-----------------------------+-------------------------------+-------------------------------+
SELECT span_id AS span_a_id,
get_span_start(span_start) as span_a_start,
get_span_end(span_start) as span_a_end
from pg_tracing_peek_spans
where trace_id='00000000000000000000000000000001' AND span_operation='BitmapOr' \gset
SELECT span_id AS span_b_id,
get_span_start(span_start) as span_b_start,
get_span_end(span_start) as span_b_end
from pg_tracing_peek_spans
where parent_id =:'span_a_id' and deparse_info='Index Cond: (a = 1)' \gset
SELECT span_id AS span_c_id,
get_span_start(span_start) as span_c_start,
get_span_end(span_start) as span_c_end
from pg_tracing_peek_spans
where parent_id =:'span_a_id' and deparse_info='Index Cond: (a = 2)' \gset
SELECT span_id AS span_d_id,
get_span_start(span_start) as span_d_start,
get_span_end(span_start) as span_d_end
from pg_tracing_peek_spans
where parent_id =:'span_a_id' and deparse_info='Index Cond: (a = 2)' \gset
SELECT :span_b_end >= :span_c_start as bitmap_or_second_child_start_after_first,
:span_c_end >= :span_d_start as bitmap_or_third_child_start_after_second,
:span_d_end <= :span_a_end as bitmap_or_ends_after_latest_child;
bitmap_or_second_child_start_after_first | bitmap_or_third_child_start_after_second | bitmap_or_ends_after_latest_child
------------------------------------------+------------------------------------------+-----------------------------------
t | t | t
(1 row)

-- Clean created spans
CALL clean_spans();
37 changes: 37 additions & 0 deletions sql/planstate_bitmap.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*dddbs='postgres.db',traceparent='00-00000000000000000000000000000001-0000000000000001-01'*/ SELECT * from pg_tracing_test where a=1 OR a=2 OR a=3;
SELECT span_operation, deparse_info, parameters, lvl from peek_ordered_spans where trace_id='00000000000000000000000000000001';

--
-- +----------------------------------------------------------------------------------------------+
-- | A: BitmapOr |
-- ++-----------------------------+-------------------------------+-------------------------------+
-- |B: Bitmap Index Scan (aid=1) |C: Bitmap Index Scan (aid=2) |D: Bitmap Index Scan (aid=3) |
-- +-----------------------------+-------------------------------+-------------------------------+

SELECT span_id AS span_a_id,
get_span_start(span_start) as span_a_start,
get_span_end(span_start) as span_a_end
from pg_tracing_peek_spans
where trace_id='00000000000000000000000000000001' AND span_operation='BitmapOr' \gset
SELECT span_id AS span_b_id,
get_span_start(span_start) as span_b_start,
get_span_end(span_start) as span_b_end
from pg_tracing_peek_spans
where parent_id =:'span_a_id' and deparse_info='Index Cond: (a = 1)' \gset
SELECT span_id AS span_c_id,
get_span_start(span_start) as span_c_start,
get_span_end(span_start) as span_c_end
from pg_tracing_peek_spans
where parent_id =:'span_a_id' and deparse_info='Index Cond: (a = 2)' \gset
SELECT span_id AS span_d_id,
get_span_start(span_start) as span_d_start,
get_span_end(span_start) as span_d_end
from pg_tracing_peek_spans
where parent_id =:'span_a_id' and deparse_info='Index Cond: (a = 2)' \gset

SELECT :span_b_end >= :span_c_start as bitmap_or_second_child_start_after_first,
:span_c_end >= :span_d_start as bitmap_or_third_child_start_after_second,
:span_d_end <= :span_a_end as bitmap_or_ends_after_latest_child;

-- Clean created spans
CALL clean_spans();
36 changes: 26 additions & 10 deletions src/pg_tracing_planstate.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,28 +232,44 @@ setup_ExecProcNode_override(QueryDesc *queryDesc, int exec_nested_level)
*/
static TimestampTz
generate_member_nodes(PlanState **planstates, int nplans, planstateTraceContext * planstateTraceContext, uint64 parent_id,
uint64 query_id, TimestampTz parent_start, TimestampTz root_end, TimestampTz *latest_end)
uint64 query_id, TimestampTz fallback_start, TimestampTz root_end, TimestampTz *latest_end)
{
int j;
TimestampTz child_end;

for (j = 0; j < nplans; j++)
child_end = generate_span_from_planstate(planstates[j], planstateTraceContext, parent_id, query_id, parent_start, root_end, latest_end);
child_end = generate_span_from_planstate(planstates[j], planstateTraceContext, parent_id, query_id, fallback_start, root_end, latest_end);
return child_end;
}

/*
* Iterate over children of BitmapOr and BitmapAnd
*/
static TimestampTz
generate_bitmap_nodes(PlanState **planstates, int nplans, planstateTraceContext * planstateTraceContext, uint64 parent_id,
uint64 query_id, TimestampTz fallback_start, TimestampTz root_end, TimestampTz *latest_end)
{
int j;
/* We keep track of the end of the last sibling end to use as start */
TimestampTz sibling_end = fallback_start;

for (j = 0; j < nplans; j++)
sibling_end = generate_span_from_planstate(planstates[j], planstateTraceContext, parent_id, query_id, sibling_end, root_end, latest_end);
return sibling_end;
}

/*
* Iterate over custom scan planstates to generate span node
*/
static TimestampTz
generate_span_from_custom_scan(CustomScanState *css, planstateTraceContext * planstateTraceContext, uint64 parent_id,
uint64 query_id, TimestampTz parent_start, TimestampTz root_end, TimestampTz *latest_end)
uint64 query_id, TimestampTz fallback_start, TimestampTz root_end, TimestampTz *latest_end)
{
ListCell *cell;
TimestampTz last_end;

foreach(cell, css->custom_ps)
last_end = generate_span_from_planstate((PlanState *) lfirst(cell), planstateTraceContext, parent_id, query_id, parent_start, root_end, latest_end);
last_end = generate_span_from_planstate((PlanState *) lfirst(cell), planstateTraceContext, parent_id, query_id, fallback_start, root_end, latest_end);
return last_end;
}

Expand Down Expand Up @@ -333,7 +349,7 @@ get_parent_traced_planstate(void)
TimestampTz
generate_span_from_planstate(PlanState *planstate, planstateTraceContext * planstateTraceContext,
uint64 parent_id, uint64 query_id,
TimestampTz parent_start, TimestampTz root_end, TimestampTz *latest_end)
TimestampTz fallback_start, TimestampTz root_end, TimestampTz *latest_end)
{
ListCell *l;
uint64 span_id;
Expand All @@ -346,7 +362,7 @@ generate_span_from_planstate(PlanState *planstate, planstateTraceContext * plans

/* The node was never executed, skip it */
if (planstate->instrument == NULL)
return 0;
return fallback_start;

if (!planstate->state->es_finished && !INSTR_TIME_IS_ZERO(planstate->instrument->starttime))
{
Expand All @@ -366,7 +382,7 @@ generate_span_from_planstate(PlanState *planstate, planstateTraceContext * plans

if (planstate->instrument->total == 0)
/* The node was never executed, ignore it */
return 0;
return fallback_start;

switch (nodeTag(planstate->plan))
{
Expand All @@ -380,7 +396,7 @@ generate_span_from_planstate(PlanState *planstate, planstateTraceContext * plans
* their start. Fallback to the parent start. TODO: Use the child
* start as a fallback instead
*/
span_start = parent_start;
span_start = fallback_start;
break;
default:
traced_planstate = get_traced_planstate(planstate);
Expand Down Expand Up @@ -473,11 +489,11 @@ generate_span_from_planstate(PlanState *planstate, planstateTraceContext * plans
((MergeAppendState *) planstate)->ms_nplans, planstateTraceContext, span_id, query_id, span_start, root_end, latest_end);
break;
case T_BitmapAnd:
generate_member_nodes(((BitmapAndState *) planstate)->bitmapplans,
generate_bitmap_nodes(((BitmapAndState *) planstate)->bitmapplans,
((BitmapAndState *) planstate)->nplans, planstateTraceContext, span_id, query_id, span_start, root_end, latest_end);
break;
case T_BitmapOr:
generate_member_nodes(((BitmapOrState *) planstate)->bitmapplans,
generate_bitmap_nodes(((BitmapOrState *) planstate)->bitmapplans,
((BitmapOrState *) planstate)->nplans, planstateTraceContext, span_id, query_id, span_start, root_end, latest_end);
break;
case T_SubqueryScan:
Expand Down

0 comments on commit 4e08652

Please sign in to comment.