andygrove opened a new issue, #2665:
URL: https://github.com/apache/datafusion-ballista/issues/2665

   **Is your feature request related to a problem or challenge? Please describe 
what you are trying to do.**
   
   Join cardinality estimates downstream of a shuffle are degenerate because a 
resolved exchange carries no distinct counts. Without NDV, DataFusion's 
`estimate_inner_join_cardinality` uses each side's row count as its NDV, so an 
inner join is estimated at the smaller input's row count. For a key/foreign-key 
join whose large side is the foreign key, that undercounts by the join's 
fan-out.
   
   In TPC-H q21 at SF1000 (#2662), `(supplier ⋈ nation) ⋈ lineitem` was 
estimated at 399,809 rows and produced 151,688,609. AQE broadcast it on that 
estimate and the job failed (#2661, fixed for that case by #2663 by measuring 
before broadcasting). The same blind spot will mislead any join reordering, 
which is the biggest q21 win.
   
   #2664 (closing #1960) carries per-column statistics from completed stages 
onto the AQE `ExchangeExec`, but only null counts are collected today.
   
   **Describe the solution you'd like**
   
   Collect approximate distinct counts with HyperLogLog on the shuffle write 
path and report them as `ColumnStatistics::distinct_count` 
(`Precision::Inexact`) on resolved exchanges.
   
   The protocol already reserves the slot: `TaskColumnStats.sketches` is a 
`repeated ColumnSketch` with `SketchType::SKETCH_TYPE_HLL`, currently always 
empty.
   
   1. **Executor**: in the three shuffle writers (passthrough, range and sort), 
update an HLL per column alongside the null counts (`ColumnNullCounts` in 
`shuffle_writer.rs`, `column_null_counts` in `sort_shuffle/writer.rs`), and 
serialize its registers into `ColumnSketch { type: HLL, data }` in 
`DefaultQueryStageExec::collect_column_stats`.
   2. **Scheduler**: in `RunningStage::output_column_stats`, merge each 
column's sketches across successful tasks (HLL registers merge by element-wise 
max) and set `distinct_count` to `Inexact(count)`. Leave it `Absent` if any 
successful task didn't report a sketch for the column, as is done for 
`null_count`.
   3. Nothing else is needed downstream: #2664 already passes 
`output_column_stats` through `resolve_stage_partitions` to 
`ExchangeExec::partition_statistics`.
   
   Open questions:
   
   - **Which columns.** A precision-14 HLL is 16 KB per column per task, and 
task completion is a hot message (see the TODO on `SuccessfulTask` in 
`ballista.proto`). Sketching only the columns that can be join or grouping keys 
downstream (the shuffle's hash-partitioning expressions at least) keeps that 
bounded. Lower precision (e.g. p=12, 4 KB, ~1.6% error) is another lever.
   - **Implementation.** DataFusion's `HyperLogLog` 
(`datafusion-functions-aggregate/src/hyperloglog.rs`) is `pub(crate)`, so 
Ballista either needs a small local implementation (hash with 
`datafusion_common::hash_utils::HLL_RANDOM_STATE` for consistency with 
`approx_distinct`), an upstream PR to make it public, or a crate.
   - **Cost.** Hashing every value of the sketched columns on the write path. 
It should be measured on TPC-H SF1000 before being on by default; a config flag 
to disable it is probably worth having.
   
   **Describe alternatives you've considered**
   
   - Exact distinct counts: unbounded memory on the write path.
   - Per-partition sketches on `PartitionStats.column_stats` (the proto has 
`distinct_count` there too). For a hash-partitioned key, per-partition NDVs 
would sum exactly, but this multiplies the payload by the partition count. 
Stage-level sketches are enough for join estimation.
   
   **Additional context**
   
   Part of #2662. Builds on #2664 / #1960 and the original collection work in 
#1916 (#1827).
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to