Repository navigation
fix(arrow-select): merge dictionaries in merge and merge_n instead of panicking on key overflow - #11925
Conversation
… panicking on key overflow
|
Thanks for taking a look, @Rich-T-kid! On benchmarks: the common path does the same work as before. Agreed that the fallback could avoid |
yes this is what I was referring to, we should add a benchmark case where it will trigger this merging. Id recommend including it in this PR as it should be straight forward & minimal. this isn't a very strong opinion though, if you'd like to do it in a follow up PR thats also fine |
…at merges dictionaries
|
Makes sense, added it here in 9f1e1c9. Locally, for 8192 rows, the fallback is ~2x slower at 50% true (~63µs vs ~121µs) and ~3x at 90% true (~19µs vs ~61µs), which gives a baseline for remapping the keys directly later. |
| // 2 x 50 values fit in Int8 keys when the dictionaries are concatenated, | ||
| // 2 x 100 values do not, so merging them has to merge the dictionaries | ||
| for (description, distinct) in [ | ||
| ("array_vs_array_concatenated_values_fit", 50), |
There was a problem hiding this comment.
if there are existing benchmarks that cover the case where dictionarys fit within the key space I think we should remove this.
There was a problem hiding this comment.
There isn't one at the moment: before this PR, merge_kernels.rs only benchmarked i32, strings and binary, so no merge benchmark used dictionary inputs at all. This case is the only baseline for dictionaries whose concatenated values still fit the key type (the MutableArrayData path), and it lets the overflow case below be compared against it. I'd like to keep it for that reason, but I'm happy to drop it if you'd rather keep only the overflow case.
There was a problem hiding this comment.
okay thanks for checking
Rich-T-kid
left a comment
There was a problem hiding this comment.
thanks for the iteration @ninglinLiu
|
run benchmark merge_kernels |
|
🤖 Benchmark starting (GKE) | trigger Target: merge_kernels Sharding factor: 1 (1 workers). Comparing fix/merge-dict-overflow (9f1e1c9) to 69be95c (merge-base) diff Run configurationrun benchmark merge_kernels
env:
BENCH_FILTER: merge_8192_from_int8_dictionaries
shards: 1
Results will be posted when all workers finish. File an issue against this benchmark runner |
|
🤖 Benchmark completed (GKE) | trigger Target: merge_kernels Comparing fix/merge-dict-overflow (9f1e1c9) to 69be95c (merge-base) diff Run configurationrun benchmark merge_kernels
env:
BENCH_FILTER: merge_8192_from_int8_dictionaries
shards: 1
DetailsPer-runner informationmerge_kernels — shard 1/1Node: gk3-benchmark-cluster-nap-gqz8246l-d890b5d1-9gw5 Instance: c4a-highmem-16 (12 vCPU / 65 GiB) uname: BENCH_COMMAND: cargo bench --features=arrow,async,test_common,experimental,object_store --bench merge_kernelsCPU Details (lscpu)Resource Usagebase (merge-base)
branch
File an issue against this benchmark runner |
Which issue does this PR close?
mergeandmerge_npanic on dictionaries whose combined values overflow the key type #11834Rationale for this change
mergeandmerge_nbuild their output with the infallibleMutableArrayData::new, which concatenates the input dictionaries and panics withDictionaryKeyOverflowErrorwhen the combined values do not fit the key type, even when every input has the same values and a merged dictionary would fit.concatandinterleavealready merge dictionaries in that case.What changes are included in this PR?
MutableArrayData::try_new. OnDictionaryKeyOverflowErrorthey fall back tointerleave, which merges the dictionaries (or returns an error if the merged dictionary still does not fit). Other errors are returned as before, and the non-dictionary fast path is unchanged.mergebuilds the(array, row)pairs from the mask, treating null mask entries as false and reading row 0 for a scalar side, the same way the slice-based path does.merge_nbuilds the pairs from the indices.interleavehas no null index, soNonerows read from an extra one-row null array of the same type.mergewith two scalars delegates tozip, which is handled by fix(arrow-select): merge dictionaries in zip instead of panicking on key overflow #11663, so it is not touched here.Are these changes tested?
Yes. Two new tests use two
Int8-keyed dictionaries with the same 100 values, so concatenation overflows but the merged dictionary fits:test_merge_dictionaries_whose_combined_values_overflow_the_key_type: array/array, array/scalar and scalar/array, with a null in the mask and a null key in the input.test_merge_n_dictionaries_whose_combined_values_overflow_the_key_type:Option<usize>indices withNonerows and a null key.Both panic on
mainand pass with this change.cargo test -p arrow-selectandcargo clippy -p arrow-select --all-targets -- -D warningspass.Are there any user-facing changes?
mergeandmerge_nreturn a merged dictionary instead of panicking. No API changes.This PR was prepared with AI assistance and reviewed/tested by the author.