Skip to content

Commit fad0b7e

Browse files
Default duckdb-bench to the V2 scan for TPC-DS and ClickBench (#11047)
Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk>
1 parent 89c5009 commit fad0b7e

7 files changed

Lines changed: 274 additions & 128 deletions

File tree

‎benchmarks/duckdb-bench/src/main.rs‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ struct Args {
103103
)]
104104
reuse: bool,
105105

106-
/// Use the planner-driven V2 Vortex scan (defaults to true for TPC-H).
106+
/// Use the planner-driven V2 Vortex scan (defaults to true for TPC-H, TPC-DS and ClickBench).
107107
#[arg(long, action = clap::ArgAction::Set)]
108108
scan_v2: Option<bool>,
109109
}
@@ -117,8 +117,10 @@ fn main() -> anyhow::Result<()> {
117117
let opts = Opts::from(args.options);
118118

119119
let scan_v2 = args.scan_v2.unwrap_or_else(|| {
120-
matches!(args.benchmark, BenchmarkArg::TpcH)
121-
&& !std::env::var("VORTEX_SCAN_V2").is_ok_and(|v| v == "0")
120+
matches!(
121+
args.benchmark,
122+
BenchmarkArg::TpcH | BenchmarkArg::TpcDS | BenchmarkArg::ClickBench
123+
) && !std::env::var("VORTEX_SCAN_V2").is_ok_and(|v| v == "0")
122124
});
123125
vortex_duckdb::set_scan_v2(scan_v2);
124126

‎vortex-duckdb/src/exporter/mod.rs‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,26 @@ mod tests {
422422
}
423423
}
424424

425+
#[test]
426+
fn test_set_validity_values_with_bit_buffer_offset() {
427+
let logical_type = LogicalType::new(DUCKDB_TYPE::DUCKDB_TYPE_BIGINT);
428+
let mut vector = Vector::with_capacity(&logical_type, 100);
429+
430+
let bits = (0..80).map(|i| i % 3 == 0).collect::<Vec<_>>();
431+
let bit_buffer = BitBuffer::from(bits.as_slice()).slice(2..80);
432+
assert_eq!(bit_buffer.offset(), 2);
433+
let mask = Mask::from(bit_buffer);
434+
435+
let all_null = unsafe { vector.set_validity_zero_copy(&mask, 5, 60, None) };
436+
437+
assert!(!all_null);
438+
439+
let validity = unsafe { vector.validity_bitslice_mut(60).unwrap() };
440+
for i in 0..60 {
441+
assert_eq!(validity[i], bits[i + 2 + 5]);
442+
}
443+
}
444+
425445
#[test]
426446
fn test_set_validity_values_64bit_alignment() {
427447
let logical_type = LogicalType::new(DUCKDB_TYPE::DUCKDB_TYPE_BIGINT);

‎vortex-duckdb/src/exporter/vector.rs‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,11 @@ impl VectorRef {
6060
unsafe { self.set_validity_data(u64_offset, len, validity_data) };
6161
} else {
6262
debug_assert!(zero_copy.is_none() || !offset.is_multiple_of(64));
63-
let source = values.bit_buffer().inner().as_slice();
63+
let bits = values.bit_buffer();
6464
copy_from_slice(
6565
unsafe { self.ensure_validity_slice(len) },
66-
source,
67-
offset,
66+
bits.inner().as_slice(),
67+
bits.offset() + offset,
6868
len,
6969
);
7070
}

‎vortex-duckdb/src/file_reader.rs‎

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ use object_store::registry::ObjectStoreRegistry;
1111
use url::Url;
1212
use vortex::array::ArrayRef;
1313
use vortex::array::VortexSessionExecute as _;
14+
use vortex::array::arrays::Chunked;
15+
use vortex::array::arrays::chunked::ChunkedArrayExt as _;
1416
use vortex::array::arrays::struct_::StructArrayExt as _;
17+
use vortex::array::scalar_fn::fns::dynamic::DynamicExprUpdates;
1518
use vortex::dtype::FieldPath;
1619
use vortex::error::VortexExpect;
1720
use vortex::error::VortexResult;
@@ -221,7 +224,16 @@ pub fn reader_initialize(file: &mut OpenFileReader, global: &GlobalState) -> Vor
221224
// global lock.
222225
if global.scan_v2 {
223226
let state = file.scan_state();
224-
let scan = FileScan::try_new(v2_builder(state, global))?;
227+
let splits = ScanBuilder::new(SESSION.clone(), Arc::clone(&state.reader))
228+
.with_projection(global.projection.clone())
229+
.with_some_filter(global.filter.filter.clone())
230+
.full_file_splits()?;
231+
let dynamic = global
232+
.filter
233+
.filter
234+
.as_ref()
235+
.is_some_and(|filter| DynamicExprUpdates::new(filter).is_some());
236+
let scan = FileScan::try_new(v2_builder(state, global), &splits, dynamic)?;
225237
if state.v2.set(scan).is_err() {
226238
vortex_panic!("file initialized twice");
227239
}
@@ -284,8 +296,23 @@ fn next_split_item(local: &mut LocalState) -> VortexResult<SplitItem> {
284296
.v2
285297
.get()
286298
.vortex_expect("V2 split of a file without a V2 scan");
287-
let Some(array) = scan.next_array(&mut local.run)? else {
288-
return Ok(SplitItem::Done);
299+
let array = match local.pending.pop() {
300+
Some(array) => array,
301+
None => {
302+
let Some(array) = scan.next_array(&mut local.run)? else {
303+
return Ok(SplitItem::Done);
304+
};
305+
// A V2 batch can join chunks of several layout chunks. Canonicalizing it
306+
// would decode their dictionaries, so export each chunk on its own, as a V1
307+
// scan yields them.
308+
match array.as_opt::<Chunked>() {
309+
Some(chunked) => {
310+
local.pending.extend(chunked.chunks().into_iter().rev());
311+
local.pending.pop().unwrap_or(array)
312+
}
313+
None => array,
314+
}
315+
}
289316
};
290317
local.split = Some(Split::V2);
291318
Ok(if array.is_empty() {

0 commit comments

Comments
 (0)