Skip to content

Commit 1b710cc

Browse files
committed
Speed up retract_batch using a hash map
1 parent 768e95e commit 1b710cc

1 file changed

Lines changed: 29 additions & 8 deletions

File tree

‎datafusion/functions-aggregate/src/median.rs‎

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ use datafusion_functions_aggregate_common::aggregate::groups_accumulator::accumu
5353
use datafusion_functions_aggregate_common::aggregate::groups_accumulator::nulls::filtered_null_mask;
5454
use datafusion_functions_aggregate_common::utils::GenericDistinctBuffer;
5555
use datafusion_macros::user_doc;
56+
use std::collections::HashMap;
5657

5758
make_udaf_expr_and_func!(
5859
Median,
@@ -298,15 +299,35 @@ impl<T: ArrowNumericType> Accumulator for MedianAccumulator<T> {
298299
}
299300

300301
fn retract_batch(&mut self, values: &[ArrayRef]) -> Result<()> {
301-
let values = values[0].as_primitive::<T>();
302-
for v in values.iter().flatten() {
303-
if let Some(idx) = self.all_values.iter().position(|x| *x == v) {
304-
self.all_values.swap_remove(idx);
305-
} else {
306-
return Err(internal_datafusion_err!(
307-
"attempted to retract value {v:?} that was not present"
308-
));
302+
let mut to_remove: HashMap<ScalarValue, usize> = HashMap::new();
303+
304+
let arr = &values[0];
305+
for i in 0..arr.len() {
306+
let v = ScalarValue::try_from_array(arr, i)?;
307+
if !v.is_null() {
308+
*to_remove.entry(v).or_default() += 1;
309+
}
310+
}
311+
312+
let mut i = 0;
313+
while i < self.all_values.len() {
314+
let k = ScalarValue::new_primitive::<T>(
315+
Some(self.all_values[i]),
316+
&self.data_type,
317+
)?;
318+
if let Some(count) = to_remove.get_mut(&k)
319+
&& *count > 0
320+
{
321+
self.all_values.swap_remove(i);
322+
*count -= 1;
323+
if *count == 0 {
324+
to_remove.remove(&k);
325+
if to_remove.is_empty() {
326+
break;
327+
}
328+
}
309329
}
330+
i += 1;
310331
}
311332
Ok(())
312333
}

0 commit comments

Comments
 (0)