Skip to content

Commit bae2cb4

Browse files
bench: cover timestamp grouping with SUM
1 parent 0e99463 commit bae2cb4

1 file changed

Lines changed: 57 additions & 9 deletions

File tree

‎datafusion/core/benches/aggregate_query_sql.rs‎

Lines changed: 57 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@
1717

1818
mod data_utils;
1919

20-
use arrow::datatypes::{DataType, IntervalUnit, TimeUnit};
20+
use arrow::array::{Array, AsArray};
21+
use arrow::datatypes::{
22+
DataType, Int32Type, Int64Type, IntervalUnit, TimeUnit, TimestampNanosecondType,
23+
};
2124
use criterion::{Criterion, criterion_group, criterion_main};
2225
use data_utils::create_table_provider;
2326
use datafusion::datasource::MemTable;
@@ -440,23 +443,47 @@ fn fully_ordered(c: &mut Criterion) {
440443
let mut group = c.benchmark_group("fully_ordered");
441444
for (name, key_expr, key_type, run_length) in cases {
442445
let ctx = rt
443-
.block_on(fully_ordered_context(key_expr, &key_type, run_length))
446+
.block_on(fully_ordered_context(
447+
key_expr, &key_type, run_length, false,
448+
))
444449
.unwrap();
445450
group.bench_function(name, |b| {
446451
b.iter(|| query(ctx.clone(), &rt, FULLY_ORDERED_QUERY))
447452
});
448453
}
454+
// Add accumulator work for one representative timestamp case without
455+
// multiplying every key type and run length by the aggregate expression.
456+
let ctx = rt
457+
.block_on(fully_ordered_context(
458+
"arrow_cast(signed_key, 'Timestamp(Nanosecond)')",
459+
&Timestamp(Nanosecond, None),
460+
31,
461+
true,
462+
))
463+
.unwrap();
464+
group.bench_function("timestamp_ns_sum", |b| {
465+
b.iter(|| query(ctx.clone(), &rt, FULLY_ORDERED_SUM_QUERY))
466+
});
449467
group.finish();
450468
}
451469

452470
const FULLY_ORDERED_QUERY: &str = "SELECT k1, k2 FROM ordered_input GROUP BY k1, k2";
471+
const FULLY_ORDERED_SUM_QUERY: &str =
472+
"SELECT k1, k2, SUM(v) FROM ordered_input GROUP BY k1, k2";
453473

454474
async fn fully_ordered_context(
455475
key_expr: &str,
456476
key_type: &DataType,
457477
run_length: usize,
478+
with_sum: bool,
458479
) -> Result<Arc<Mutex<SessionContext>>> {
459480
const ROWS: usize = 2_097_152;
481+
// Use source row numbers as nonconstant values for the aggregate case.
482+
let (value_projection, input_value, sql) = if with_sum {
483+
(", v", ", value AS v", FULLY_ORDERED_SUM_QUERY)
484+
} else {
485+
("", "", FULLY_ORDERED_QUERY)
486+
};
460487
let config = SessionConfig::new()
461488
.with_target_partitions(1)
462489
.with_batch_size(8192)
@@ -467,10 +494,10 @@ async fn fully_ordered_context(
467494
let input = ctx
468495
.sql(&format!(
469496
"SELECT CAST(group_id / 32 AS INTEGER) AS k1, \
470-
CASE WHEN key_value = 0 THEN NULL ELSE {key_expr} END AS k2 \
497+
CASE WHEN key_value = 0 THEN NULL ELSE {key_expr} END AS k2{value_projection} \
471498
FROM (SELECT value / {run_length} AS group_id, \
472499
value / {run_length} % 32 AS key_value, \
473-
value / {run_length} % 32 - 16 AS signed_key \
500+
value / {run_length} % 32 - 16 AS signed_key{input_value} \
474501
FROM range({ROWS})) \
475502
ORDER BY k1 ASC NULLS FIRST, k2 ASC NULLS FIRST"
476503
))
@@ -492,11 +519,7 @@ async fn fully_ordered_context(
492519
]]);
493520
ctx.register_table("ordered_input", Arc::new(table))?;
494521

495-
let plan = ctx
496-
.sql(FULLY_ORDERED_QUERY)
497-
.await?
498-
.create_physical_plan()
499-
.await?;
522+
let plan = ctx.sql(sql).await?.create_physical_plan().await?;
500523
let description = displayable(plan.as_ref()).indent(true).to_string();
501524
assert!(
502525
description.contains("group_clustering_mode=Full"),
@@ -511,6 +534,31 @@ async fn fully_ordered_context(
511534
result.iter().map(|batch| batch.num_rows()).sum::<usize>(),
512535
ROWS.div_ceil(run_length)
513536
);
537+
if with_sum {
538+
let rows = i64::try_from(ROWS).unwrap();
539+
let run_length = i64::try_from(run_length).unwrap();
540+
for batch in &result {
541+
let k1 = batch.column(0).as_primitive::<Int32Type>();
542+
let k2 = batch.column(1).as_primitive::<TimestampNanosecondType>();
543+
let sums = batch.column(2).as_primitive::<Int64Type>();
544+
assert_eq!(sums.null_count(), 0);
545+
for row in 0..batch.num_rows() {
546+
// Each input group covers a contiguous range of source row
547+
// numbers. Recover it from the keys, independently of output
548+
// order, and check the arithmetic-series sum, including the
549+
// final short group and groups with a NULL timestamp key.
550+
let key_offset = if k2.is_null(row) {
551+
0
552+
} else {
553+
k2.value(row) + 16
554+
};
555+
let group_id = i64::from(k1.value(row)) * 32 + key_offset;
556+
let start = group_id * run_length;
557+
let end = (start + run_length).min(rows);
558+
assert_eq!(sums.value(row), (start + end - 1) * (end - start) / 2);
559+
}
560+
}
561+
}
514562
Ok(Arc::new(Mutex::new(ctx)))
515563
}
516564

0 commit comments

Comments
 (0)