ghostiee-11 commented on issue #7647:
URL: https://github.com/apache/datafusion/issues/7647#issuecomment-4883024528

   > Filed with AI assistance per the project's policy. The repro was written 
and run against datafusion 54.0.0 (pyarrow 23.0.0, arrow-rs 58.3.0); the source 
analysis below is mine and was reviewed before posting.
   
   Related to this issue: on datafusion 54 a dictionary group key whose 
combined cardinality across partitions exceeds its key width fails hard, rather 
than just being suboptimal.
   
   ## Repro (pure datafusion + pyarrow, no network)
   
   ```python
   import numpy as np, pyarrow as pa
   from datafusion import SessionContext
   
   PER_PARTITION, N_PARTITIONS = 100, 50  # combined 5000 >> Int8 max (127)
   parts = []
   for p in range(N_PARTITIONS):
       values = pa.array(np.arange(p*PER_PARTITION, 
p*PER_PARTITION+PER_PARTITION, dtype=np.int64))
       keys = pa.array(np.arange(PER_PARTITION, dtype=np.int8))
       k = pa.DictionaryArray.from_arrays(keys, values)  # valid 
Dictionary(Int8, Int64) per batch
       parts.append(pa.record_batch({"k": k, "v": 
pa.array(np.ones(PER_PARTITION))}))
   
   ctx = SessionContext()
   ctx.register_record_batches("t", [[b] for b in parts])
   ctx.sql("SELECT k, SUM(v) FROM t GROUP BY k").to_arrow_table()
   # -> Arrow error: Dictionary key bigger than the key type
   ```
   
   Each partition is a valid `Dictionary(Int8, Int64)` (<=128 distinct), but 
the partitions hold disjoint values, so the combined group-key set is 5000.
   
   ## Mechanism (datafusion 54)
   
   - `Aggregate::group_fields` (physical-plan/src/aggregates/mod.rs) keeps the 
dictionary type for the group key.
   - `GroupValuesRows::emit` decodes the keys via the RowConverter, then 
`dictionary_encode_if_necessary` (group_values/row.rs) re-encodes them back 
into the narrow dictionary because the group schema says so.
   - Across `RepartitionExec: Hash` / `FinalPartitioned`, the combined set 
exceeds Int8, so the re-encode overflows. arrow-rs is behaving correctly here 
(`concat` is type-preserving, so it errors in `merge_dictionary_values` rather 
than silently widening); the decision to keep a narrow key for the combined 
group keys is the datafusion side.
   
   `#8291` materialized dict group keys to the value type and avoided this; 
that path is not present in 54. This issue and `#21765` are moving toward 
keeping dictionaries and optimizing on them, which is great for low cardinality 
but needs to handle the case where the combined cardinality outgrows the key 
width.
   
   ## Question before I send a PR
   
   Two ways to fix it, and I would rather match your direction:
   
   - **A. Decode** dict group keys to their value type at plan time (restores 
`#8291` semantics). Simple, output type changes to the value type.
   - **B. Widen** the group key to a safe key width (e.g. Int32/Int64) and keep 
a dictionary output (aligns with `#21765`). Preserves "group by dict returns 
dict".
   
   I have both a candidate patch and a sqllogictest ready. Which direction do 
you prefer for the aggregate group-key path? Happy to open the PR against 
whichever you pick.
   


-- 
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