Is your feature request related to a problem or challenge?
PrimitiveDistinctCountAccumulator::update_batch inserts values with a per-element Option check (if let Some(value) = value) on every row, even when the input array has no nulls. This is the hot path for COUNT(DISTINCT <int/date/time/decimal>).
The same accumulator's merge_batch already inserts wholesale from the values buffer (self.values.extend(list.values())), so the fast path is available — it's just not applied on the update path.
Describe the solution you'd like
When array.null_count() == 0, insert directly from the values buffer, skipping the per-element validity branch — mirroring merge_batch and the null-free fast paths recently added to percentile_cont/median in #23954. Measured ~66% faster on the null-free count_distinct benchmark.
Is your feature request related to a problem or challenge?
PrimitiveDistinctCountAccumulator::update_batchinserts values with a per-elementOptioncheck (if let Some(value) = value) on every row, even when the input array has no nulls. This is the hot path forCOUNT(DISTINCT <int/date/time/decimal>).The same accumulator's
merge_batchalready inserts wholesale from the values buffer (self.values.extend(list.values())), so the fast path is available — it's just not applied on the update path.Describe the solution you'd like
When
array.null_count() == 0, insert directly from the values buffer, skipping the per-element validity branch — mirroringmerge_batchand the null-free fast paths recently added topercentile_cont/medianin #23954. Measured ~66% faster on the null-freecount_distinctbenchmark.