Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/columnar.h
Original file line number Diff line number Diff line change
Expand Up @@ -932,6 +932,7 @@ typedef struct PgColumnarGroupStats
uint64 groupsTotal;
uint64 groupsRead;
uint64 groupsRemoved;
uint64 vectorsSkipped;
} PgColumnarGroupStats;

extern void PgColumnarExplainPushedDown(int64 nfilters, ExplainState *es);
Expand Down
12 changes: 10 additions & 2 deletions src/columnar_customscan.c
Original file line number Diff line number Diff line change
Expand Up @@ -2170,6 +2170,15 @@ PgColumnarExplainGroupStats(const PgColumnarGroupStats *stats, ExplainState *es)
(int64) stats->groupsRead, es);
ExplainPropertyInteger("Columnar Chunk Groups Removed by Filter", NULL,
(int64) stats->groupsRemoved, es);
/*
* Vectors skipped belongs with the group counters rather than beside them:
* it was printed by the scalar node alone, so a plan could not say whether
* per-vector skipping happened on the vectorized aggregate path -- the path
* where it matters most, since #512 is about the fold and the skip vector
* disagreeing and this is the number that would show it.
*/
ExplainPropertyInteger("Columnar Vectors Skipped", NULL,
(int64) stats->vectorsSkipped, es);
}

/* -------------------------------------------------------------------------
Expand Down Expand Up @@ -2298,9 +2307,8 @@ PgColumnarExplainCustomScan(CustomScanState *node, List *ancestors,
gs.groupsTotal = groupsTotal;
gs.groupsRead = groupsRead;
gs.groupsRemoved = groupsSkipped;
gs.vectorsSkipped = PgColumnarVectorsSkipped(cstate->readState);
PgColumnarExplainGroupStats(&gs, es);
ExplainPropertyInteger("Columnar Vectors Skipped", NULL,
(int64) PgColumnarVectorsSkipped(cstate->readState), es);

/*
* Rows the qual rejected before their remaining projected columns were
Expand Down
7 changes: 7 additions & 0 deletions src/columnar_vector.c
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,7 @@ typedef struct PgColumnarAggScanState
bool haveStats;
uint64 groupsRead;
uint64 groupsSkipped;
uint64 vectorsSkipped;
uint64 groupsTotal;

/*
Expand Down Expand Up @@ -696,6 +697,7 @@ typedef struct PgColumnarGroupAggScanState
bool haveStats;
uint64 groupsRead;
uint64 groupsSkipped;
uint64 vectorsSkipped;
uint64 groupsTotal;
int usablePreds; /* of npreds, how many can exclude (#479) */
} PgColumnarGroupAggScanState;
Expand Down Expand Up @@ -3268,6 +3270,7 @@ pgcolumnar_native_batch_fold(PgColumnarAggScanState *state, Relation rel,
PgColumnarReadStats(rs, &state->groupsRead, &state->groupsSkipped,
&state->groupsTotal);
state->usablePreds = PgColumnarReadUsablePredicates(rs);
state->vectorsSkipped = PgColumnarVectorsSkipped(rs);
state->haveStats = true;
state->batchFolded = true;
PgColumnarEndRead(rs);
Expand Down Expand Up @@ -3402,6 +3405,7 @@ pgcolumnar_native_scan_agg(PgColumnarAggScanState *state,
PgColumnarReadStats(rs, &state->groupsRead, &state->groupsSkipped,
&state->groupsTotal);
state->usablePreds = PgColumnarReadUsablePredicates(rs);
state->vectorsSkipped = PgColumnarVectorsSkipped(rs);
state->haveStats = true;
}

Expand Down Expand Up @@ -3558,6 +3562,7 @@ PgColumnarExplainAggScan(CustomScanState *node, List *ancestors, ExplainState *e
gs.groupsTotal = state->groupsTotal;
gs.groupsRead = state->groupsRead;
gs.groupsRemoved = state->groupsSkipped;
gs.vectorsSkipped = state->vectorsSkipped;
PgColumnarExplainGroupStats(&gs, es);
}
}
Expand Down Expand Up @@ -4119,6 +4124,7 @@ pgcolumnar_groupagg_build(PgColumnarGroupAggScanState *state)
PgColumnarReadStats(rs, &state->groupsRead, &state->groupsSkipped,
&state->groupsTotal);
state->usablePreds = PgColumnarReadUsablePredicates(rs);
state->vectorsSkipped = PgColumnarVectorsSkipped(rs);
state->haveStats = true;

PgColumnarEndRead(rs);
Expand Down Expand Up @@ -4238,6 +4244,7 @@ PgColumnarExplainGroupAggScan(CustomScanState *node, List *ancestors,
gs.groupsTotal = state->groupsTotal;
gs.groupsRead = state->groupsRead;
gs.groupsRemoved = state->groupsSkipped;
gs.vectorsSkipped = state->vectorsSkipped;
PgColumnarExplainGroupStats(&gs, es);
}
}
Expand Down
36 changes: 36 additions & 0 deletions test/native_vecskip.sh
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,42 @@ check "no whole group removed" "$(counter 'Columnar Chunk Groups Removed by Filt
check "non-selective removes no vectors" \
"$(counter 'Columnar Vectors Skipped' 'SELECT id FROM n WHERE id > 0')" "0"

# ---- the vectorized aggregate must report the counter too --------------------
#
# "Columnar Vectors Skipped" is emitted by the scalar node only. The two
# vectorized aggregate nodes print Chunk Groups Total/Read/Removed, Usable Skip
# Predicates and Vector Predicates -- but not this one -- so a plan cannot say
# whether per-vector skipping happened on the aggregate path. That is the path
# where it matters most: #512 is precisely about the fold and the skip vector
# disagreeing, and the number that would show it is the one not printed.
#
# Same table, same predicate as the scalar checks above, so the two arms differ
# only in the node.
# pgcolumnar.enable_ungrouped_vector_agg defaults to OFF, so the aggregate node
# has to be asked for. Without the SET this falls back to the scalar scan -- which
# is what the first version of this check did, and the premise below caught it
# passing for that reason.
AGGQ="SELECT count(*), sum(v) FROM n WHERE id BETWEEN 100 AND 200"
explain_agg() {
env PATH="$PGC_BINDIR:$PATH" psql -h 127.0.0.1 -p "$PGC_PORT" -U postgres \
-d "$PGC_DB" -At \
-c "SET pgcolumnar.enable_ungrouped_vector_agg = on;
EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF, SUMMARY OFF) $1" 2>/dev/null
}

# Premise, and it has teeth: if the planner declines the vectorized aggregate,
# this query falls back to the scalar scan -- which DOES print the line, so the
# check below would pass while testing nothing at all.
check "premise: the aggregate arm really is a vectorized aggregate" \
"$(explain_agg "$AGGQ" | grep -q 'Columnar Vectorized Aggregates' && echo yes || echo no)" \
"yes"
check "premise: and it is not the scalar scan" \
"$(explain_agg "$AGGQ" | grep -q 'Columnar Projected Columns' && echo yes || echo no)" "no"

check "the vectorized aggregate reports Columnar Vectors Skipped" \
"$(explain_agg "$AGGQ" | grep -q 'Columnar Vectors Skipped' && echo yes || echo no)" \
"yes"

# Boundary and cross-vector ranges still return exactly the heap rows.
check "cross-vector range parity" \
"$(pgc_set_hash 'SELECT id, v FROM n WHERE id BETWEEN 2000 AND 5000')" \
Expand Down
Loading