Repository: spiraldb/vortex
Pull request #3192: Add datafusion tpcds and generate all tpc* data with duckdb 
Author: login: joseph-isaacs
Created: 2025-05-01T15:41:26Z | Merged: 2025-05-02T15:01:14Z

This uses decimal for tpch benchmarks, expect a perf drop!
I will enable CI in a future PR


Diff:
diff --git a/bench-vortex/src/bin/clickbench.rs b/bench-vortex/src/bin/clickbench.rs
index a3b3a2865a5..bc1e8689612 100644
--- a/bench-vortex/src/bin/clickbench.rs
+++ b/bench-vortex/src/bin/clickbench.rs
@@ -208,7 +208,14 @@ fn main() -> anyhow::Result<()> {
         .targets
         .iter()
         .any(|t| t.engine() == Engine::DuckDB)
-        .then(|| ddb::build_and_get_executable_path(&args.duckdb_path, false));
+        .then(|| {
+            let path = ddb::get_executable_path(&args.duckdb_path);
+            // If the path is to the duckdb-vortex extension, try to rebuild
+            if args.duckdb_path.is_none() {
+                ddb::build_vortex_duckdb();
+            }
+            path
+        });
 
     for target in args.targets.iter() {
         let engine = target.engine();
@@ -230,13 +237,12 @@ fn main() -> anyhow::Result<()> {
 
         let tokio_runtime = new_tokio_runtime(args.threads);
 
-        init_data_source(
+        tokio_runtime.block_on(init_data_source(
             file_format,
             &base_url,
             args.single_file,
             &engine_ctx,
-            &tokio_runtime,
-        )?;
+        ))?;
 
         let bench_measurements = execute_queries(
             &queries,
@@ -357,12 +363,11 @@ fn data_source_base_url(remote_data_dir: &Option<String>, flavor: Flavor) -> any
 /// Configures the data source format for benchmark queries based on the specified format and engine.
 ///
 /// Parquet files are registered directly. Vortex files are created form Parquet files.
-fn init_data_source(
+async fn init_data_source(
     file_format: Format,
     base_url: &Url,
     single_file: bool,
     engine_ctx: &EngineCtx,
-    tokio_runtime: &Runtime,
 ) -> anyhow::Result<()> {
     let dataset = BenchmarkDataset::ClickBench { single_file };
 
@@ -370,15 +375,15 @@ fn init_data_source(
         let file_path = base_url
             .to_file_path()
             .map_err(|_| anyhow::anyhow!("invalid file URL: {}", base_url))?;
-        tokio_runtime.block_on(bench_vortex::file::convert_parquet_to_vortex(
-            &file_path, dataset,
-        ))?
+        bench_vortex::file::convert_parquet_to_vortex(&file_path, dataset).await?
     }
 
     match engine_ctx {
         EngineCtx::DataFusion(ctx) => match file_format {
             Format::Parquet | Format::OnDiskVortex => {
-                dataset.register_tables(&ctx.session, base_url, file_format)?
+                dataset
+                    .register_tables(&ctx.session, base_url, file_format)
+                    .await?
             }
             _ => {
                 vortex_panic!(
diff --git a/bench-vortex/src/bin/tpcds.rs b/bench-vortex/src/bin/tpcds.rs
index ef2e672ab59..c3c42e0c33f 100644
--- a/bench-vortex/src/bin/tpcds.rs
+++ b/bench-vortex/src/bin/tpcds.rs
@@ -1,16 +1,19 @@
 use std::path::{Path, PathBuf};
+use std::time::{Duration, Instant};
 
 use bench_vortex::ddb::{DuckDBExecutor, register_tables};
 use bench_vortex::display::{DisplayFormat, print_measurements_json, render_table};
 use bench_vortex::measurements::QueryMeasurement;
-use bench_vortex::tpcds::{benchmark_duckdb_query, tpcds_queries};
+use bench_vortex::tpcds::{benchmark_duckdb_query, run_datafusion_tpcds_query, tpcds_queries};
 use bench_vortex::tpch::duckdb::{DuckdbTpcOptions, TpcDataset, generate_tpc};
-use bench_vortex::utils::{TPCDS_DATASET, new_tokio_runtime};
+use bench_vortex::tpch::load_datasets;
+use bench_vortex::utils::{TPCDS_DATASET, TPCH_DATASET, new_tokio_runtime};
 use bench_vortex::{BenchmarkDataset, Engine, IdempotentPath, Target, ddb, default_env_filter};
 use clap::{Parser, value_parser};
+use datafusion::prelude::SessionContext;
 use indicatif::ProgressBar;
 use itertools::Itertools;
-use log::{info, warn};
+use log::info;
 use tempfile::tempdir;
 use url::Url;
 use vortex::error::VortexExpect;
@@ -93,27 +96,28 @@ fn main() -> anyhow::Result<()> {
         .unique()
         .collect_vec();
 
-    let duckdb_resolved_path =
-        ddb::build_and_get_executable_path(&args.duckdb_path, args.skip_rebuild);
+    let duckdb_resolved_path = ddb::get_executable_path(&args.duckdb_path);
+    if args.duckdb_path.is_none() && !args.skip_rebuild {
+        ddb::build_vortex_duckdb();
+    }
 
     for format in formats {
-        let opts = DuckdbTpcOptions::default()
-            .with_scale_factor(1)
-            .with_base_dir("tpcds".to_data_path())
-            .with_dataset(TpcDataset::TpcDs)
-            .with_duckdb_path(duckdb_resolved_path.clone())
-            .with_format(format);
+        let opts = DuckdbTpcOptions::new("tpcds".to_data_path(), TpcDataset::TpcDs, format)
+            .with_duckdb_path(duckdb_resolved_path.clone());
         generate_tpc(opts).expect("gen tpch-ds");
     }
 
     let url = Url::parse(
-        ("file:".to_owned()
-            + "tpcds"
+        format!(
+            "file:{}/{}/",
+            "tpcds"
                 .to_data_path()
                 .to_str()
-                .vortex_expect("path should be utf8")
-            + "/")
-            .as_ref(),
+                .vortex_expect("path must be utf8"),
+            // scale factor 1
+            1
+        )
+        .as_ref(),
     )?;
 
     let runtime = new_tokio_runtime(None);
@@ -122,7 +126,6 @@ fn main() -> anyhow::Result<()> {
         args.queries,
         args.exclude_queries,
         args.iterations,
-        1,
         args.targets,
         args.display_format,
         url,
@@ -140,7 +143,6 @@ async fn bench_main(
     queries: Option<Vec<usize>>,
     exclude_queries: Option<Vec<usize>>,
     iterations: usize,
-    scale_factor: usize,
     targets: Vec<Target>,
     display_format: DisplayFormat,
     url: Url,
@@ -181,10 +183,6 @@ async fn bench_main(
                     .path()
                     .join(format!("duckdb-file-{}.db", format.name()));
 
-                let url = url
-                    .join(&format!("{scale_factor}/"))
-                    .vortex_expect("cannot join scale factor");
-
                 let executor = DuckDBExecutor::new(duckdb_path.to_owned(), duckdb_file);
                 register_tables(&executor, &url, format, BenchmarkDataset::TpcDS)?;
 
@@ -205,9 +203,29 @@ async fn bench_main(
                     progress.inc(1);
                 }
             }
-            _ => {
-                warn!("Engine {:?} not supported for TPC-H benchmarks", engine);
+            Engine::DataFusion => {
+                // TODO: add schemas for tpcds.
+                let ctx = load_datasets(&url, format, BenchmarkDataset::TpcDS, true).await?;
+
+                for (query_idx, sql_queries) in tpch_queries.clone() {
+                    // Run benchmark as an async function
+                    let fastest_run =
+                        benchmark_datafusion_query(&sql_queries, iterations, &ctx).await;
+
+                    let storage = bench_vortex::utils::url_scheme_to_storage(&url)?;
+
+                    measurements.push(QueryMeasurement {
+                        query_idx,
+                        target: *target,
+                        storage,
+                        fastest_run,
+                        dataset: TPCH_DATASET.to_owned(),
+                    });
+
+                    progress.inc(1);
+                }
             }
+            _ => todo!(),
         }
     }
 
@@ -223,3 +241,22 @@ async fn bench_main(
     };
     Ok(())
 }
+
+async fn benchmark_datafusion_query(
+    query_string: &str,
+    iterations: usize,
+    context: &SessionContext,
+) -> Duration {
+    let mut fastest_run = Duration::from_millis(u64::MAX);
+
+    for _ in 0..iterations {
+        let start = Instant::now();
+        // TODO(joe): add row count
+        let _q_row_count = run_datafusion_tpcds_query(context, query_string).await;
+        let elapsed = start.elapsed();
+
+        fastest_run = fastest_run.min(elapsed);
+    }
+
+    fastest_run
+}
diff --git a/bench-vortex/src/bin/tpch.rs b/bench-vortex/src/bin/tpch.rs
index 6e298d3eee2..c607229dadd 100644
--- a/bench-vortex/src/bin/tpch.rs
+++ b/bench-vortex/src/bin/tpch.rs
@@ -8,7 +8,7 @@ use bench_vortex::df::write_execution_plan;
 use bench_vortex::display::{DisplayFormat, print_measurements_json, render_table};
 use bench_vortex::measurements::QueryMeasurement;
 use bench_vortex::metrics::{MetricsSetExt, export_plan_spans};
-use bench_vortex::tpch::dbgen::{DBGen, DBGenOptions};
+use bench_vortex::tpch::duckdb::{DuckdbTpcOptions, TpcDataset, generate_tpc};
 use bench_vortex::tpch::{
     EXPECTED_ROW_COUNTS_SF1, EXPECTED_ROW_COUNTS_SF10, TPC_H_ROW_COUNT_ARRAY_LENGTH, load_datasets,
     run_tpch_query, tpch_queries,
@@ -16,7 +16,7 @@ use bench_vortex::tpch::{
 use bench_vortex::utils::constants::TPCH_DATASET;
 use bench_vortex::utils::new_tokio_runtime;
 use bench_vortex::{
-    BenchmarkDataset, Engine, Format, Target, ddb, default_env_filter, vortex_panic,
+    BenchmarkDataset, Engine, Format, IdempotentPath, Target, ddb, default_env_filter, vortex_panic,
 };
 use clap::{Parser, ValueEnum, value_parser};
 use datafusion::execution::context::SessionContext;
@@ -123,34 +123,34 @@ fn main() -> anyhow::Result<()> {
         _guard
     };
 
+    let formats = args.targets.iter().map(|t| t.format()).collect_vec();
+
     let runtime = new_tokio_runtime(args.threads);
 
+    let duckdb_resolved_path = ddb::get_executable_path(&args.duckdb_path);
+    if args.duckdb_path.is_none() && !args.skip_rebuild {
+        ddb::build_vortex_duckdb();
+    }
+
     let url = match args.use_remote_data_dir {
         None => {
-            let data_dir = match args.data_generator {
-                DataGenerator::Dbgen => {
-                    let db_gen_options =
-                        DBGenOptions::default().with_scale_factor(args.scale_factor);
-                    DBGen::new(db_gen_options).generate()?
-                }
-                DataGenerator::Duckdb => todo!("not implemented yet, will be support this soon"),
-                // TODO(joe) re-enable this once its correct.
-                // DataGenerator::Duckdb => {
-                //     generate_tpc(DuckdbTpcOptions::default().with_scale_factor(args.scale_factor))?
-                // }
-            };
+            for format in formats {
+                // Arrow uses csv
+                let format = if format == Format::Arrow {
+                    Format::Csv
+                } else {
+                    format
+                };
+                let opts = DuckdbTpcOptions::new("tpch".to_data_path(), TpcDataset::TpcH, format)
+                    .with_duckdb_path(duckdb_resolved_path.clone());
+                generate_tpc(opts)?;
+            }
 
-            info!(
-                "Using existing or generating new files located at {}.",
-                data_dir.display()
-            );
-            Url::parse(
-                format!(
-                    "file:{}/",
-                    data_dir.to_str().vortex_expect("path should be utf8")
-                )
-                .as_ref(),
-            )?
+            let data_dir = "tpch".to_data_path();
+            let data_dir = data_dir.to_str().vortex_expect("path must be utf8");
+
+            info!("Using existing or generating new files located at {data_dir}.");
+            Url::parse(format!("file:{data_dir}/{}/", args.scale_factor).as_ref())?
         }
         Some(tpch_benchmark_remote_data_dir) => {
             // e.g. "s3://vortex-bench-dev-eu/parquet/"
@@ -187,8 +187,7 @@ fn main() -> anyhow::Result<()> {
         args.all_metrics,
         args.export_spans,
         args.emit_plan,
-        &args.duckdb_path,
-        args.skip_rebuild,
+        duckdb_resolved_path,
     ))
 }
 
@@ -306,8 +305,7 @@ async fn bench_main(
     display_all_metrics: bool,
     export_spans: bool,
     emit_plan: bool,
-    duckdb_path: &Option<PathBuf>,
-    skip_duckdb_build: bool,
+    duckdb_resolved_path: PathBuf,
 ) -> anyhow::Result<()> {
     let expected_row_counts = if scale_factor == 1 {
         EXPECTED_ROW_COUNTS_SF1
@@ -346,17 +344,18 @@ async fn bench_main(
 
     assert!(!tpch_queries.is_empty(), "No queries to run");
 
-    let duckdb_resolved_path = targets
-        .iter()
-        .any(|t| t.engine() == Engine::DuckDB)
-        .then(|| ddb::build_and_get_executable_path(duckdb_path, skip_duckdb_build));
-
     for target in &targets {
         let engine = target.engine();
         let format = target.format();
         match engine {
             Engine::DataFusion => {
-                let ctx = load_datasets(&url, format, disable_datafusion_cache).await?;
+                let ctx = load_datasets(
+                    &url,
+                    format,
+                    BenchmarkDataset::TpcH,
+                    disable_datafusion_cache,
+                )
+                .await?;
 
                 let mut plans = Vec::new();
 
@@ -408,13 +407,12 @@ async fn bench_main(
             }
             // TODO(joe); ensure that files are downloaded before running duckdb.
             Engine::DuckDB => {
-                let duckdb_path = duckdb_resolved_path.as_ref().vortex_expect("created above");
                 let temp_dir = tempdir()?;
                 let duckdb_file = temp_dir
                     .path()
                     .join(format!("duckdb-file-{}.db", format.name()));
 
-                let executor = DuckDBExecutor::new(duckdb_path.clone(), duckdb_file);
+                let executor = DuckDBExecutor::new(duckdb_resolved_path.clone(), duckdb_file);
                 register_tables(&executor, &url, format, BenchmarkDataset::TpcH)?;
 
                 for (query_idx, sql_queries) in tpch_queries.clone() {
diff --git a/bench-vortex/src/clickbench.rs b/bench-vortex/src/clickbench.rs
index 76f4b4e9d97..20125bf3e2f 100644
--- a/bench-vortex/src/clickbench.rs
+++ b/bench-vortex/src/clickbench.rs
@@ -197,11 +197,11 @@ pub async fn convert_parquet_to_vortex(input_path: &Path) -> anyhow::Result<()>
     Ok(())
 }
 
-pub fn register_vortex_files(
+pub async fn register_vortex_files(
     session: SessionContext,
     table_name: &str,
     input_path: &Url,
-    schema: &Schema,
+    schema: Option<Schema>,
     single_file: bool,
 ) -> anyhow::Result<()> {
     let mut vortex_path = input_path.join("vortex/")?;
@@ -215,9 +215,17 @@ pub fn register_vortex_files(
 
     let table_url = ListingTableUrl::parse(vortex_path)?;
 
-    let config = ListingTableConfig::new(table_url)
-        .with_listing_options(ListingOptions::new(format))
-        .with_schema(schema.clone().into());
+    let config =
+        ListingTableConfig::new(table_url).with_listing_options(ListingOptions::new(format));
+
+    let config = if let Some(schema) = schema {
+        config.with_schema(schema.into())
+    } else {
+        config
+            .infer_schema(&session.state())
+            .await
+            .vortex_expect("cannot infer schema")
+    };
 
     let listing_table = Arc::new(ListingTable::try_new(config)?);
     session.register_table(table_name, listing_table)?;
diff --git a/bench-vortex/src/datasets/file.rs b/bench-vortex/src/datasets/file.rs
index 28b48488021..7a9405bed9d 100644
--- a/bench-vortex/src/datasets/file.rs
+++ b/bench-vortex/src/datasets/file.rs
@@ -1,4 +1,3 @@
-use std::fs;
 use std::path::{Path, PathBuf};
 use std::sync::Arc;
 
@@ -9,21 +8,18 @@ use datafusion::datasource::listing::{
     ListingOptions, ListingTable, ListingTableConfig, ListingTableUrl,
 };
 use datafusion::prelude::{ParquetReadOptions, SessionContext};
-use futures::StreamExt;
 use object_store::ObjectStore;
 use object_store::path::Path as ObjectStorePath;
 use tokio::fs::OpenOptions;
 use tracing::info;
 use url::Url;
-use vortex::TryIntoArray;
-use vortex::dtype::arrow::FromArrowType;
-use vortex::file::{VORTEX_FILE_EXTENSION, VortexWriteOptions};
+use vortex::error::VortexExpect;
+use vortex::file::VortexWriteOptions;
 use vortex_datafusion::persistent::VortexFormat;
 
 use crate::conversions::parquet_to_vortex;
 use crate::datasets::BenchmarkDataset;
 use crate::idempotent_async;
-use crate::tpch::named_locks::with_lock;
 
 pub async fn convert_parquet_to_vortex(input_path: &Path, dataset: BenchmarkDataset) -> Result<()> {
     match dataset {
@@ -43,26 +39,13 @@ pub async fn register_parquet_files(
     object_store: Arc<dyn ObjectStore>,
     table_name: &str,
     file_url: &Url,
-    schema: &Schema,
+    schema: Option<Schema>,
     dataset: BenchmarkDataset,
 ) -> Result<()> {
     match dataset {
         BenchmarkDataset::TpcH => {
-            let mut parquet_url = file_url.clone();
-            if file_url.path().ends_with(".tbl") {
-                // Replace .tbl with .parquet in the path
-                let parquet_path = file_url.path().replace(".tbl", ".parquet");
-                parquet_url.set_path(&parquet_path);
-            }
-
-            ensure_parquet_file_exists(
-                session,
-                object_store.as_ref(),
-                file_url,
-                &parquet_url,
-                schema,
-            )
-            .await?;
+            let parquet_url = file_url.clone();
+            ensure_parquet_file_exists(object_store.as_ref(), &parquet_url).await?;
 
             session
                 .register_parquet(
@@ -85,8 +68,16 @@ pub async fn register_parquet_files(
             let table_url = ListingTableUrl::parse(parquet_path)?;
 
             let config = ListingTableConfig::new(table_url)
-                .with_listing_options(ListingOptions::new(format))
-                .with_schema(schema.clone().into());
+                .with_listing_options(ListingOptions::new(format));
+
+            let config = if let Some(schema) = schema {
+                config.with_schema(schema.into())
+            } else {
+                config
+                    .infer_schema(&session.state())
+                    .await
+                    .vortex_expect("cannot infer schema")
+            };
 
             let listing_table = Arc::new(ListingTable::try_new(config)?);
             session.register_table(table_name, listing_table)?;
@@ -99,93 +90,25 @@ pub async fn register_parquet_files(
 
 pub async fn register_vortex_files(
     session: &SessionContext,
-    object_store: Arc<dyn ObjectStore>,
+    _object_store: Arc<dyn ObjectStore>,
     table_name: &str,
     file_url: &Url,
-    schema: &Schema,
+    schema: Option<Schema>,
     dataset: BenchmarkDataset,
 ) -> Result<()> {
     match dataset {
-        BenchmarkDataset::TpcH => {
-            // Extract the filename from the URL
-            let csv_basename = file_url
-                .path_segments()
-                .expect("url path not empty")
-                .next_back();
-            let vortex_basename = csv_basename
-                .unwrap()
-                .replace(".tbl", (".".to_owned() + VORTEX_FILE_EXTENSION).as_ref());
-
-            // Calculate vortex directory path
-            let vortex_dir = dataset.vortex_path(file_url)?;
-            let vtx_file = &vortex_dir.join(vortex_basename.as_ref())?;
-
-            if let Err(e) = object_store
-                .head(&ObjectStorePath::parse(vtx_file.path())?)
-                .await
-            {
-                info!(
-                    "Checking if file exists: File {} doesn't exist because {e}",
-                    vtx_file
-                );
-
-                if vtx_file.scheme() == "file" {
-                    // Create directory if it doesn't exist
-                    if let Some(parent) = Path::new(vtx_file.path()).parent() {
-                        fs::create_dir_all(parent)?;
-                    }
-
-                    with_lock(vtx_file.path().to_owned(), async move || {
-                        // First convert CSV to record batches
-                        let record_batches = session
-                            .read_csv(
-                                file_url.as_str(),
-                                datafusion::prelude::CsvReadOptions::default()
-                                    .delimiter(b'|')
-                                    .has_header(false)
-                                    .file_extension("tbl")
-                                    .schema(schema),
-                            )
-                            .await?
-                            .execute_stream()
-                            .await?;
-
-                        let adapter = vortex::stream::ArrayStreamAdapter::new(
-                            vortex::dtype::DType::from_arrow(record_batches.schema()),
-                            record_batches.then(|batch| async move {
-                                batch
-                                    .map_err(vortex::error::VortexError::from)
-                                    .and_then(|b| b.try_into_array())
-                            }),
-                        );
-
-                        let array_stream = Box::pin(adapter)
-                            as std::pin::Pin<Box<dyn vortex::stream::ArrayStream + Send>>;
-
-                        // Write to file
-                        let f = OpenOptions::new()
-                            .write(true)
-                            .truncate(true)
-                            .create(true)
-                            .open(vtx_file.path())
-                            .await?;
-                        VortexWriteOptions::default().write(f, array_stream).await?;
-
-                        anyhow::Ok(())
-                    })
-                    .await?;
-                } else {
-                    anyhow::bail!("Writing to remote storage not supported");
-                }
-            }
-
+        BenchmarkDataset::TpcH | BenchmarkDataset::TpcDS => {
             // Register the Vortex file
             let format = Arc::new(VortexFormat::default());
-            let table_url = ListingTableUrl::parse(vtx_file.as_str())?;
+            let table_url = ListingTableUrl::parse(file_url.as_str())?;
             let config = ListingTableConfig::new(table_url)
-                .with_listing_options(ListingOptions::new(format))
-                .infer_schema(&session.state())
-                .await?;
+                .with_listing_options(ListingOptions::new(format));
+
+            let config = if let Some(schema) = schema {
+                config.with_schema(schema.into())
+            } else {
+                config.infer_schema(&session.state()).await?
+            };
 
             let listing_table = Arc::new(ListingTable::try_new(config)?);
             session.register_table(table_name, listing_table)?;
@@ -197,20 +120,17 @@ pub async fn register_vortex_files(
                 file_url,
                 schema,
                 single_file,
-            )?;
+            )
+            .await?;
         }
-        _ => todo!(),
     }
 
     Ok(())
 }
 
 async fn ensure_parquet_file_exists(
-    session: &SessionContext,
     object_store: &dyn ObjectStore,
-    file_url: &Url,
     parquet_url: &Url,
-    schema: &Schema,
 ) -> Result<()> {
     let parquet_path = parquet_url.path();
 
@@ -219,28 +139,13 @@ async fn ensure_parquet_file_exists(
         .await
     {
         info!(
-            "Checking if file exist: File {} doesn't exist because {e}",
+            "Asserting file exist: File {} doesn't exist because {e}",
             parquet_url.as_str()
         );
 
         if parquet_url.scheme() != "file" {
             anyhow::bail!("Writing to S3 does not seem to work!");
         }
-
-        with_lock(parquet_path.to_owned(), async move || {
-            crate::conversions::csv_to_parquet_file(
-                session,
-                datafusion::prelude::CsvReadOptions::default()
-                    .delimiter(b'|')
-                    .has_header(false)
-                    .file_extension("tbl")
-                    .schema(schema),
-                file_url.as_str(),
-                parquet_path,
-            )
-            .await
-        })
-        .await?;
     }
 
     Ok(())
diff --git a/bench-vortex/src/datasets/mod.rs b/bench-vortex/src/datasets/mod.rs
index fc2bdca9cd2..fd675f4c977 100644
--- a/bench-vortex/src/datasets/mod.rs
+++ b/bench-vortex/src/datasets/mod.rs
@@ -6,7 +6,7 @@ use datafusion::prelude::SessionContext;
 use url::Url;
 use vortex::ArrayRef;
 
-use crate::Format;
+use crate::{Format, clickbench};
 
 pub mod data_downloads;
 pub mod file;
@@ -84,25 +84,14 @@ impl BenchmarkDataset {
     }
 
     pub fn parquet_path(&self, base_url: &Url) -> Result<Url> {
-        match self {
-            BenchmarkDataset::TpcH => {
-                // TPC-H parquet files are stored alongside the TBL files
-                Ok(base_url.clone())
-            }
-            BenchmarkDataset::ClickBench { .. } | BenchmarkDataset::TpcDS => {
-                // ClickBench parquet files are stored in "parquet/" subdirectory
-                Ok(base_url.join("parquet/")?)
-            }
-        }
+        Ok(base_url.join("parquet/")?)
     }
 
     pub fn vortex_path(&self, base_url: &Url) -> Result<Url> {
         match self {
-            BenchmarkDataset::TpcH => {
-                // TPC-H vortex files are stored in "vortex_compressed/" subdirectory
-                Ok(base_url.join("vortex_compressed/")?)
+            BenchmarkDataset::TpcH | BenchmarkDataset::TpcDS => {
+                Ok(base_url.join(&format!("{}/", Format::OnDiskVortex))?)
             }
-            BenchmarkDataset::TpcDS => Ok(base_url.join(&format!("{}/", Format::OnDiskVortex))?),
             BenchmarkDataset::ClickBench { .. } => {
                 // ClickBench vortex files are stored in "vortex/" subdirectory
                 Ok(base_url.join("vortex/")?)
@@ -110,7 +99,7 @@ impl BenchmarkDataset {
         }
     }
 
-    pub fn register_tables(
+    pub async fn register_tables(
         &self,
         session: &SessionContext,
         base_url: &Url,
@@ -122,22 +111,23 @@ impl BenchmarkDataset {
                 // TPC-H tables are handled separately
             }
             (BenchmarkDataset::ClickBench { single_file }, Format::Parquet) => {
-                crate::clickbench::register_parquet_files(
+                clickbench::register_parquet_files(
                     session,
                     "hits",
                     base_url,
-                    &crate::clickbench::HITS_SCHEMA,
+                    &clickbench::HITS_SCHEMA,
                     *single_file,
                 )?;
             }
             (BenchmarkDataset::ClickBench { single_file }, Format::OnDiskVortex) => {
-                crate::clickbench::register_vortex_files(
+                clickbench::register_vortex_files(
                     session.clone(),
                     "hits",
                     base_url,
-                    &crate::clickbench::HITS_SCHEMA,
+                    Some(clickbench::HITS_SCHEMA.clone()),
                     *single_file,
-                )?;
+                )
+                .await?;
             }
             (BenchmarkDataset::ClickBench { .. }, _) => {
                 anyhow::bail!("Unsupported format for ClickBench: {}", format);
diff --git a/bench-vortex/src/datasets/tpch_l_comment.rs b/bench-vortex/src/datasets/tpch_l_comment.rs
index 208665806e6..cd86b0bbf11 100644
--- a/bench-vortex/src/datasets/tpch_l_comment.rs
+++ b/bench-vortex/src/datasets/tpch_l_comment.rs
@@ -4,8 +4,9 @@ use vortex::dtype::FieldName;
 use vortex::{Array, ArrayExt, ArrayRef, ToCanonical};
 
 use crate::datasets::Dataset;
-use crate::tpch;
-use crate::tpch::dbgen::{DBGen, DBGenOptions};
+use crate::ddb::get_executable_path;
+use crate::tpch::duckdb::{DuckdbTpcOptions, TpcDataset, generate_tpc};
+use crate::{Format, IdempotentPath, tpch};
 
 pub struct TPCHLCommentChunked;
 
@@ -16,7 +17,11 @@ impl Dataset for TPCHLCommentChunked {
     }
 
     async fn to_vortex_array(&self) -> ArrayRef {
-        let data_dir = DBGen::new(DBGenOptions::default()).generate().unwrap();
+        let duckdb_resolved_path = get_executable_path(&None);
+        let opts = DuckdbTpcOptions::new("tpch".to_data_path(), TpcDataset::TpcH, Format::Csv)
+            .with_duckdb_path(duckdb_resolved_path.clone());
+        let data_dir = generate_tpc(opts).expect("gen tpch");
+
         let lineitem_vortex = tpch::load_table(data_dir, "lineitem", &tpch::schema::LINEITEM).await;
 
         let lineitem_chunked = lineitem_vortex.as_::<ChunkedArray>();
diff --git a/bench-vortex/src/engines/ddb/mod.rs b/bench-vortex/src/engines/ddb/mod.rs
index e2bb438df2e..a5aa86bb0ec 100644
--- a/bench-vortex/src/engines/ddb/mod.rs
+++ b/bench-vortex/src/engines/ddb/mod.rs
@@ -38,11 +38,7 @@ impl DuckDBExecutor {
     }
 }
 
-/// Finds the path to the DuckDB executable
-pub fn build_and_get_executable_path(
-    user_supplied_path_flag: &Option<PathBuf>,
-    skip_duckdb_build: bool,
-) -> PathBuf {
+pub fn get_executable_path(user_supplied_path_flag: &Option<PathBuf>) -> PathBuf {
     let validate_path = |duckdb_path: &PathBuf| {
         assert!(
             duckdb_path.as_path().exists(),
@@ -77,40 +73,61 @@ pub fn build_and_get_executable_path(
         .expect("failed to find the vortex repo")
         .join("duckdb-vortex");
 
-    if !skip_duckdb_build {
-        let mut command = Command::new("make");
-        command
-            .current_dir(&duckdb_vortex_path)
-            .env("GEN", "ninja")
-            .arg("release");
-
-        info!(
-            "Building duckdb vortex extension at {}, with command {:?}",
-            duckdb_vortex_path.display(),
-            command
-        );
+    let duckdb_path = duckdb_vortex_path.join("build/release/duckdb");
+
+    validate_path(&duckdb_path);
+
+    duckdb_path
+}
 
-        let output = command
-            .output()
-            .expect("Trying to build duckdb vortex extension");
+/// Finds the path to the DuckDB executable
+pub fn build_vortex_duckdb() {
+    // Try to find the 'vortex' top-level directory. This is preferred over logic along
+    // the lines of `git rev-parse --show-toplevel`, as the repository uses submodules.
+    let mut repo_root = None;
+    let mut current_dir = std::env::current_dir().expect("failed to get current dir");
 
-        if !output.status.success() {
-            let stdout = String::from_utf8_lossy(&output.stdout);
-            let stderr = String::from_utf8_lossy(&output.stderr);
-            vortex_panic!("duckdb failed: stdout=\"{stdout}\", stderr=\"{stderr}\"");
+    while current_dir.file_name().is_some() {
+        if current_dir.file_name().and_then(|name| name.to_str()) == Some("vortex") {
+            repo_root = Some(current_dir.to_string_lossy().into_owned());
+            break;
         }
 
-        info!(
-            "Built duckdb vortex extension at {}",
-            duckdb_vortex_path.display()
-        );
+        if !current_dir.pop() {
+            break;
+        }
     }
 
-    let duckdb_path = duckdb_vortex_path.join("build/release/duckdb");
+    let duckdb_vortex_path = PathBuf::from_str(&repo_root.unwrap_or_else(|| ".".to_string()))
+        .expect("failed to find the vortex repo")
+        .join("duckdb-vortex");
 
-    validate_path(&duckdb_path);
+    let mut command = Command::new("make");
+    command
+        .current_dir(&duckdb_vortex_path)
+        .env("GEN", "ninja")
+        .arg("release");
 
-    duckdb_path
+    info!(
+        "Building duckdb vortex extension at {}, with command {:?}",
+        duckdb_vortex_path.display(),
+        command
+    );
+
+    let output = command
+        .output()
+        .expect("Trying to build duckdb vortex extension");
+
+    if !output.status.success() {
+        let stdout = String::from_utf8_lossy(&output.stdout);
+        let stderr = String::from_utf8_lossy(&output.stderr);
+        vortex_panic!("duckdb failed: stdout=\"{stdout}\", stderr=\"{stderr}\"");
+    }
+
+    info!(
+        "Built duckdb vortex extension at {}",
+        duckdb_vortex_path.display()
+    );
 }
 
 enum DuckDBObject {
@@ -183,6 +200,7 @@ fn create_table_registration(
 }
 
 /// Resolves the storage URL based on dataset and format requirements
+#[allow(dead_code)]
 fn resolve_storage_url(base_url: &Url, file_format: Format, dataset: BenchmarkDataset) -> Url {
     if file_format == Format::OnDiskVortex {
         match dataset.vortex_path(base_url) {
@@ -229,7 +247,9 @@ pub fn register_tables(
         f => f,
     };
 
+    // println!("base url {}", base_url);
     let effective_url = resolve_storage_url(base_url, load_format, dataset);
+    // let effective_url = base_url;
     let extension = match load_format {
         Format::Parquet => "parquet",
         Format::OnDiskVortex => "vortex",
diff --git a/bench-vortex/src/lib.rs b/bench-vortex/src/lib.rs
index c1b76721683..b918fe2d610 100644
--- a/bench-vortex/src/lib.rs
+++ b/bench-vortex/src/lib.rs
@@ -130,6 +130,17 @@ impl Format {
             Format::OnDiskDuckDB => "duckdb",
         }
     }
+
+    pub fn ext(&self) -> &'static str {
+        match self {
+            Format::Csv => "csv",
+            Format::Arrow => "arrow",
+            Format::Parquet => "parquet",
+            Format::InMemoryVortex => unreachable!("no extension"),
+            Format::OnDiskVortex => "vortex",
+            Format::OnDiskDuckDB => "duckdb",
+        }
+    }
 }
 
 #[derive(ValueEnum, Clone, Copy, Debug, Hash, Default, PartialEq, Eq, Serialize)]
diff --git a/bench-vortex/src/tpcds/mod.rs b/bench-vortex/src/tpcds/mod.rs
index 343a24bf11c..8bb5247b41c 100644
--- a/bench-vortex/src/tpcds/mod.rs
+++ b/bench-vortex/src/tpcds/mod.rs
@@ -1,12 +1,14 @@
 use std::fs;
 use std::path::Path;
+use std::sync::Arc;
 use std::time::Duration;
 
 use datafusion::prelude::SessionContext;
+use datafusion_physical_plan::ExecutionPlan;
 use url::Url;
 
 use crate::ddb::DuckDBExecutor;
-use crate::df::get_session_context;
+use crate::df::{execute_query, get_session_context};
 use crate::{Format, ddb, vortex_panic};
 
 pub async fn load_datasets(_base_dir: &Url, _format: Format) -> anyhow::Result<SessionContext> {
@@ -40,3 +42,11 @@ pub fn benchmark_duckdb_query(
         fastest.min(duration)
     })
 }
+
+pub async fn run_datafusion_tpcds_query(
+    ctx: &SessionContext,
+    query: &str,
+) -> (usize, Arc<dyn ExecutionPlan>) {
+    let (record_batches, metrics) = execute_query(ctx, query).await.unwrap();
+    (record_batches.iter().map(|r| r.num_rows()).sum(), metrics)
+}
diff --git a/bench-vortex/src/tpch/duckdb.rs b/bench-vortex/src/tpch/duckdb.rs
index 6a63b9d289f..8e5544c509c 100644
--- a/bench-vortex/src/tpch/duckdb.rs
+++ b/bench-vortex/src/tpch/duckdb.rs
@@ -1,4 +1,3 @@
-use std::fs;
 use std::path::{Path, PathBuf};
 use std::process::Command;
 use std::time::Duration;
@@ -6,8 +5,8 @@ use std::time::Duration;
 use anyhow::Result;
 use xshell::Shell;
 
+use crate::Format;
 use crate::ddb::DuckDBExecutor;
-use crate::{Format, IdempotentPath};
 
 pub enum TpcDataset {
     TpcH,
@@ -41,13 +40,13 @@ impl DuckdbTpcOptions {
     }
 }
 
-impl Default for DuckdbTpcOptions {
-    fn default() -> Self {
+impl DuckdbTpcOptions {
+    pub fn new(base_dir: PathBuf, dataset: TpcDataset, format: Format) -> Self {
         Self {
             scale_factor: 1,
-            base_dir: "tpch-duckdb".to_data_path(),
-            dataset: TpcDataset::TpcH,
-            format: Format::Csv,
+            base_dir,
+            dataset,
+            format,
             duckdb_path: None,
         }
     }
@@ -115,13 +114,13 @@ pub fn generate_tpc(opts: DuckdbTpcOptions) -> Result<PathBuf> {
     match opts.format {
         Format::Csv => {
             command.arg("-c").arg(format!(
-                "export database '{}' (format CSV, delimiter '|', header false);",
+                "EXPORT DATABASE '{}' (FORMAT CSV, delimiter '|', header false, FILE_EXTENSION tbl);",
                 output_dir.to_string_lossy(),
             ));
         }
         Format::Parquet => {
             command.arg("-c").arg(format!(
-                "export database '{}' (format PARQUET);",
+                "EXPORT DATABASE '{}' (format PARQUET);",
                 output_dir.to_string_lossy(),
             ));
         }
@@ -133,12 +132,11 @@ pub fn generate_tpc(opts: DuckdbTpcOptions) -> Result<PathBuf> {
             }
 
             command.arg("-c").arg(format!(
-                "export database '{}' (format VORTEX);",
+                "EXPORT DATABASE '{}' (format VORTEX);",
                 output_dir.to_string_lossy(),
             ));
         }
-        Format::OnDiskDuckDB => { /* Do nothing */ }
-        _ => todo!(),
+        Format::OnDiskDuckDB | Format::Arrow => { /* Do nothing */ }
     };
 
     let output = command.output()?;
@@ -149,14 +147,6 @@ pub fn generate_tpc(opts: DuckdbTpcOptions) -> Result<PathBuf> {
         anyhow::bail!("duckdb failed: stdout=\"{stdout}\", stderr=\"{stderr}\"");
     }
 
-    if opts.format == Format::Csv {
-        // rename .csv files into the expected .tbl extension
-        sh.read_dir(&output_dir)?
-            .into_iter()
-            .filter(|p| p.extension().is_some_and(|ext| ext == "csv"))
-            .try_for_each(|p| fs::rename(p.clone(), p.with_extension("tbl")))?;
-    }
-
     // Write a success file to indicate this scale-factor is created.
     sh.write_file(success_file, vec![])?;
 
diff --git a/bench-vortex/src/tpch/mod.rs b/bench-vortex/src/tpch/mod.rs
index f499db74b06..16965c43977 100644
--- a/bench-vortex/src/tpch/mod.rs
+++ b/bench-vortex/src/tpch/mod.rs
@@ -2,10 +2,12 @@ use std::fs;
 use std::path::Path;
 use std::sync::Arc;
 
+use anyhow::bail;
 use arrow_array::StructArray as ArrowStructArray;
 use arrow_schema::Schema;
 use datafusion::datasource::MemTable;
 use datafusion::prelude::{CsvReadOptions, SessionContext};
+use itertools::Itertools;
 use object_store::ObjectStore;
 use url::Url;
 use vortex::arrays::ChunkedArray;
@@ -14,7 +16,7 @@ use vortex::{Array, ArrayRef, TryIntoArray};
 use vortex_datafusion::SessionContextExt;
 
 use crate::engines::df::{get_session_context, make_object_store};
-use crate::{Format, datasets};
+use crate::{BenchmarkDataset, Format, datasets};
 
 pub mod dbgen;
 pub mod duckdb;
@@ -40,27 +42,45 @@ pub const EXPECTED_ROW_COUNTS_SF10: [usize; TPC_H_ROW_COUNT_ARRAY_LENGTH] = [
 pub async fn load_datasets(
     base_dir: &Url,
     format: Format,
+    dataset: BenchmarkDataset,
     disable_datafusion_cache: bool,
 ) -> anyhow::Result<SessionContext> {
     let context = get_session_context(disable_datafusion_cache);
 
     let object_store = make_object_store(&context, base_dir)?;
 
-    let files = [
-        ("customer", &schema::CUSTOMER),
-        ("lineitem", &schema::LINEITEM),
-        ("nation", &schema::NATION),
-        ("orders", &schema::ORDERS),
-        ("part", &schema::PART),
-        ("partsupp", &schema::PARTSUPP),
-        ("region", &schema::REGION),
-        ("supplier", &schema::SUPPLIER),
-    ];
-
-    for (name, path, schema) in files
-        .into_iter()
-        .map(|(name, schema)| (name, base_dir.join(&format!("{name}.tbl")), schema))
-    {
+    let files = match dataset {
+        BenchmarkDataset::TpcH => vec![
+            ("customer", Some(schema::CUSTOMER.clone())),
+            ("lineitem", Some(schema::LINEITEM.clone())),
+            ("nation", Some(schema::NATION.clone())),
+            ("orders", Some(schema::ORDERS.clone())),
+            ("part", Some(schema::PART.clone())),
+            ("partsupp", Some(schema::PARTSUPP.clone())),
+            ("region", Some(schema::REGION.clone())),
+            ("supplier", Some(schema::SUPPLIER.clone())),
+        ],
+
+        BenchmarkDataset::TpcDS => BenchmarkDataset::TpcDS
+            .tables()
+            .iter()
+            .map(|f| (*f, None))
+            .collect_vec(),
+        BenchmarkDataset::ClickBench { .. } => todo!(),
+    };
+
+    for (name, path, schema) in files.into_iter().map(|(name, schema)| {
+        let format = if format == Format::Arrow {
+            Format::Csv
+        } else {
+            format
+        };
+        (
+            name,
+            base_dir.join(&format!("{}/{name}.{}", format.name(), format.ext())),
+            schema,
+        )
+    }) {
         let path = path?;
         match format {
             Format::Csv => register_csv(&context, name, &path, schema).await?,
@@ -72,7 +92,7 @@ pub async fn load_datasets(
             Format::OnDiskVortex => {
                 register_vortex_file(&context, object_store.clone(), name, &path, schema).await?
             }
-            Format::OnDiskDuckDB => todo!(),
+            Format::OnDiskDuckDB => unreachable!("duckdb never supported with datafusion"),
         }
     }
 
@@ -111,8 +131,11 @@ async fn register_csv(
     session: &SessionContext,
     name: &str,
     file: &Url,
-    schema: &Schema,
+    schema: Option<Schema>,
 ) -> anyhow::Result<()> {
+    let Some(schema) = schema else {
+        bail!("cannot run bench with format==csv")
+    };
     session
         .register_csv(
             name,
@@ -120,8 +143,8 @@ async fn register_csv(
             CsvReadOptions::default()
                 .delimiter(b'|')
                 .has_header(false)
-                .file_extension("tbl")
-                .schema(schema),
+                .file_extension("csv")
+                .schema(&schema),
         )
         .await?;
 
@@ -132,8 +155,12 @@ async fn register_arrow(
     session: &SessionContext,
     name: &str,
     file: &Url,
-    schema: &Schema,
+    schema: Option<Schema>,
 ) -> anyhow::Result<()> {
+    let Some(schema) = schema else {
+        bail!("cannot have an arrow run without a preloaded schema")
+    };
+
     // Read CSV file into a set of Arrow RecordBatch.
     let record_batches = session
         .read_csv(
@@ -141,8 +168,8 @@ async fn register_arrow(
             CsvReadOptions::default()
                 .delimiter(b'|')
                 .has_header(false)
-                .file_extension("tbl")
-                .schema(schema),
+                .file_extension("csv")
+                .schema(&schema),
         )
         .await?
         .collect()
@@ -159,7 +186,7 @@ async fn register_parquet(
     object_store: Arc<dyn ObjectStore>,
     name: &str,
     file: &Url,
-    schema: &Schema,
+    schema: Option<Schema>,
 ) -> anyhow::Result<()> {
     datasets::file::register_parquet_files(
         session,
@@ -167,7 +194,7 @@ async fn register_parquet(
         name,
         file,
         schema,
-        crate::BenchmarkDataset::TpcH,
+        BenchmarkDataset::TpcH,
     )
     .await
 }
@@ -177,7 +204,7 @@ async fn register_vortex_file(
     object_store: Arc<dyn ObjectStore>,
     table_name: &str,
     file: &Url,
-    schema: &Schema,
+    schema: Option<Schema>,
 ) -> anyhow::Result<()> {
     datasets::file::register_vortex_files(
         session,
@@ -185,7 +212,7 @@ async fn register_vortex_file(
         table_name,
         file,
         schema,
-        crate::BenchmarkDataset::TpcH,
+        BenchmarkDataset::TpcH,
     )
     .await
 }
@@ -194,16 +221,20 @@ async fn register_vortex(
     session: &SessionContext,
     name: &str,
     file: &Url,
-    schema: &Schema,
+    schema: Option<Schema>,
 ) -> anyhow::Result<()> {
+    let Some(schema) = schema else {
+        bail!("required schema for in mem vortex")
+    };
+    // TODO(joe): use parquet for speed?
     let record_batches = session
         .read_csv(
             file.as_str(),
             CsvReadOptions::default()
                 .delimiter(b'|')
                 .has_header(false)
-                .file_extension("tbl")
-                .schema(schema),
+                .file_extension("csv")
+                .schema(&schema),
         )
         .await?
         .collect()
@@ -227,14 +258,14 @@ async fn register_vortex(
 /// Load a table as an uncompressed Vortex array.
 pub async fn load_table(data_dir: impl AsRef<Path>, name: &str, schema: &Schema) -> ArrayRef {
     // Create a local session to load the CSV file from the path.
-    let path = data_dir.as_ref().join(name).with_extension("tbl");
+    let path = data_dir.as_ref().join(name).with_extension("csv");
     let record_batches = SessionContext::new()
         .read_csv(
             path.to_str().unwrap(),
             CsvReadOptions::default()
                 .delimiter(b'|')
                 .has_header(false)
-                .file_extension("tbl")
+                .file_extension("csv")
                 .schema(schema),
         )
         .await
diff --git a/bench-vortex/src/tpch/schema.rs b/bench-vortex/src/tpch/schema.rs
index 384217d135e..8665c6f57ad 100644
--- a/bench-vortex/src/tpch/schema.rs
+++ b/bench-vortex/src/tpch/schema.rs
@@ -7,16 +7,16 @@ use arrow_schema::{DataType, Field, Schema};
 
 pub static NATION: LazyLock<Schema> = LazyLock::new(|| {
     Schema::new(vec![
-        Field::new("n_nationkey", DataType::Int64, false),
+        Field::new("n_nationkey", DataType::Int32, false),
         Field::new("n_name", DataType::Utf8View, false),
-        Field::new("n_regionkey", DataType::Int64, false),
+        Field::new("n_regionkey", DataType::Int32, false),
         Field::new("n_comment", DataType::Utf8View, true),
     ])
 });
 
 pub static REGION: LazyLock<Schema> = LazyLock::new(|| {
     Schema::new(vec![
-        Field::new("r_regionkey", DataType::Int64, false),
+        Field::new("r_regionkey", DataType::Int32, false),
         Field::new("r_name", DataType::Utf8View, false),
         Field::new("r_comment", DataType::Utf8View, true),
     ])
@@ -31,7 +31,7 @@ pub static PART: LazyLock<Schema> = LazyLock::new(|| {
         Field::new("p_type", DataType::Utf8View, false),
         Field::new("p_size", DataType::Int32, false),
         Field::new("p_container", DataType::Utf8View, false),
-        Field::new("p_retailprice", DataType::Float64, false),
+        Field::new("p_retailprice", DataType::Decimal128(15, 2), false),
         Field::new("p_comment", DataType::Utf8View, false),
     ])
 });
@@ -43,7 +43,7 @@ pub static SUPPLIER: LazyLock<Schema> = LazyLock::new(|| {
         Field::new("s_address", DataType::Utf8View, false),
         Field::new("s_nationkey", DataType::Int32, false),
         Field::new("s_phone", DataType::Utf8View, false),
-        Field::new("s_acctbal", DataType::Float64, false),
+        Field::new("s_acctbal", DataType::Decimal128(15, 2), false),
         Field::new("s_comment", DataType::Utf8View, false),
     ])
 });
@@ -53,7 +53,7 @@ pub static PARTSUPP: LazyLock<Schema> = LazyLock::new(|| {
         Field::new("ps_partkey", DataType::Int64, false),
         Field::new("ps_suppkey", DataType::Int64, false),
         Field::new("ps_availqty", DataType::Int64, false),
-        Field::new("ps_supplycost", DataType::Float64, false),
+        Field::new("ps_supplycost", DataType::Decimal128(15, 2), false),
         Field::new("ps_comment", DataType::Utf8View, false),
     ])
 });
@@ -63,9 +63,9 @@ pub static CUSTOMER: LazyLock<Schema> = LazyLock::new(|| {
         Field::new("c_custkey", DataType::Int64, false),
         Field::new("c_name", DataType::Utf8View, false),
         Field::new("c_address", DataType::Utf8View, false),
-        Field::new("c_nationkey", DataType::Int64, false),
+        Field::new("c_nationkey", DataType::Int32, false),
         Field::new("c_phone", DataType::Utf8View, false),
-        Field::new("c_acctbal", DataType::Float64, false),
+        Field::new("c_acctbal", DataType::Decimal128(15, 2), false),
         Field::new("c_mktsegment", DataType::Utf8View, false),
         Field::new("c_comment", DataType::Utf8View, false),
     ])
@@ -76,7 +76,7 @@ pub static ORDERS: LazyLock<Schema> = LazyLock::new(|| {
         Field::new("o_orderkey", DataType::Int64, false),
         Field::new("o_custkey", DataType::Int64, false),
         Field::new("o_orderstatus", DataType::Utf8View, false),
-        Field::new("o_totalprice", DataType::Float64, false),
+        Field::new("o_totalprice", DataType::Decimal128(15, 2), false),
         Field::new("o_orderdate", DataType::Date32, false),
         Field::new("o_orderpriority", DataType::Utf8View, false),
         Field::new("o_clerk", DataType::Utf8View, false),
@@ -91,10 +91,10 @@ pub static LINEITEM: LazyLock<Schema> = LazyLock::new(|| {
         Field::new("l_partkey", DataType::Int64, false),
         Field::new("l_suppkey", DataType::Int64, false),
         Field::new("l_linenumber", DataType::Int64, false),
-        Field::new("l_quantity", DataType::Float64, false),
-        Field::new("l_extendedprice", DataType::Float64, false),
-        Field::new("l_discount", DataType::Float64, false),
-        Field::new("l_tax", DataType::Float64, false),
+        Field::new("l_quantity", DataType::Decimal128(15, 2), false),
+        Field::new("l_extendedprice", DataType::Decimal128(15, 2), false),
+        Field::new("l_discount", DataType::Decimal128(15, 2), false),
+        Field::new("l_tax", DataType::Decimal128(15, 2), false),
         Field::new("l_returnflag", DataType::Utf8View, false),
         Field::new("l_linestatus", DataType::Utf8View, false),
         Field::new("l_shipdate", DataType::Date32, false),
diff --git a/duckdb-vortex/extension_config.cmake b/duckdb-vortex/extension_config.cmake
index ffbde1f20ea..8f44c85a90b 100644
--- a/duckdb-vortex/extension_config.cmake
+++ b/duckdb-vortex/extension_config.cmake
@@ -6,5 +6,6 @@ duckdb_extension_load(vortex
     LOAD_TESTS
 )
 
+# These are only build and included with the duckdb prebuild executable used locally
 duckdb_extension_load(tpch)
 duckdb_extension_load(tpcds)
diff --git a/vortex-array/src/arrays/decimal/mod.rs b/vortex-array/src/arrays/decimal/mod.rs
index 0ce05ebfc32..26c155e6473 100644
--- a/vortex-array/src/arrays/decimal/mod.rs
+++ b/vortex-array/src/arrays/decimal/mod.rs
@@ -122,7 +122,7 @@ impl DecimalArray {
             vortex_panic!(
                 "Cannot extract Buffer<{:?}> for DecimalArray with values_type {:?}",
                 T::VALUES_TYPE,
-                self.values_type
+                self.values_type,
             );
         }
         Buffer::<T>::from_byte_buffer(self.values.clone())
diff --git a/vortex-array/src/arrow/compute/to_arrow/canonical.rs b/vortex-array/src/arrow/compute/to_arrow/canonical.rs
index ebcd285735c..5303959d0c0 100644
--- a/vortex-array/src/arrow/compute/to_arrow/canonical.rs
+++ b/vortex-array/src/arrow/compute/to_arrow/canonical.rs
@@ -185,9 +185,9 @@ fn to_arrow_decimal128(array: DecimalArray) -> VortexResult<ArrowArrayRef> {
     let null_buffer = array.validity_mask()?.to_null_buffer();
     let buffer: Buffer<i128> = match array.values_type() {
         DecimalValueType::I8 => array.buffer::<i8>().into_iter().map(|x| x.as_()).collect(),
-        DecimalValueType::I16 => array.buffer::<i8>().into_iter().map(|x| x.as_()).collect(),
-        DecimalValueType::I32 => array.buffer::<i8>().into_iter().map(|x| x.as_()).collect(),
-        DecimalValueType::I64 => array.buffer::<i8>().into_iter().map(|x| x.as_()).collect(),
+        DecimalValueType::I16 => array.buffer::<i16>().into_iter().map(|x| x.as_()).collect(),
+        DecimalValueType::I32 => array.buffer::<i32>().into_iter().map(|x| x.as_()).collect(),
+        DecimalValueType::I64 => array.buffer::<i64>().into_iter().map(|x| x.as_()).collect(),
         DecimalValueType::I128 => array.buffer::<i128>(),
         DecimalValueType::I256 => {
             vortex_bail!("i256 decimals cannot be converted to Arrow i128 decimal")
diff --git a/vortex-dtype/src/arrow.rs b/vortex-dtype/src/arrow.rs
index e95c68e299a..4129f595090 100644
--- a/vortex-dtype/src/arrow.rs
+++ b/vortex-dtype/src/arrow.rs
@@ -107,9 +107,10 @@ impl FromArrowType<(&DataType, Nullability)> for DType {
 
         match data_type {
             DataType::Null => Null,
+            DataType::Decimal128(precision, scale) | DataType::Decimal256(precision, scale) => {
+                Decimal(DecimalDType::new(*precision, *scale), nullability)
+            }
             DataType::Boolean => Bool(nullability),
-            DataType::Decimal128(p, s) => Decimal(DecimalDType::new(*p, *s), nullability),
-            DataType::Decimal256(p, s) => Decimal(DecimalDType::new(*p, *s), nullability),
             DataType::Utf8 | DataType::LargeUtf8 | DataType::Utf8View => Utf8(nullability),
             DataType::Binary | DataType::LargeBinary | DataType::BinaryView => Binary(nullability),
             DataType::Date32
diff --git a/vortex-scalar/src/datafusion.rs b/vortex-scalar/src/datafusion.rs
index 951c7658f82..a4739cf29d3 100644
--- a/vortex-scalar/src/datafusion.rs
+++ b/vortex-scalar/src/datafusion.rs
@@ -7,10 +7,10 @@ use vortex_buffer::ByteBuffer;
 use vortex_dtype::datetime::arrow::make_temporal_ext_dtype;
 use vortex_dtype::datetime::{TemporalMetadata, TimeUnit, is_temporal_ext_type};
 use vortex_dtype::half::f16;
-use vortex_dtype::{DECIMAL128_MAX_PRECISION, DType, Nullability, PType};
+use vortex_dtype::{DECIMAL128_MAX_PRECISION, DType, DecimalDType, Nullability, PType};
 use vortex_error::{VortexError, vortex_bail};
 
-use crate::{DecimalValue, InnerScalarValue, PValue, Scalar};
+use crate::{DecimalValue, InnerScalarValue, PValue, Scalar, i256};
 
 impl TryFrom<Scalar> for ScalarValue {
     type Error = VortexError;
@@ -206,6 +206,32 @@ impl From<ScalarValue> for Scalar {
                         .unwrap_or_else(crate::ScalarValue::null),
                 )
             }
+            ScalarValue::Decimal128(decimal, precision, scale) => {
+                let decimal_dtype = DecimalDType::new(precision, scale);
+                let nullable = Nullability::Nullable;
+                if let Some(value) = decimal {
+                    Scalar::decimal(
+                        DecimalValue::I128(value),
+                        decimal_dtype,
+                        Nullability::Nullable,
+                    )
+                } else {
+                    Scalar::null(DType::Decimal(decimal_dtype, nullable))
+                }
+            }
+            ScalarValue::Decimal256(decimal, precision, scale) => {
+                let decimal_dtype = DecimalDType::new(precision, scale);
+                let nullable = Nullability::Nullable;
+                if let Some(value) = decimal {
+                    Scalar::decimal(
+                        DecimalValue::I256(i256::from(value)),
+                        decimal_dtype,
+                        Nullability::Nullable,
+                    )
+                } else {
+                    Scalar::null(DType::Decimal(decimal_dtype, nullable))
+                }
+            }
             _ => unimplemented!("Can't convert {value:?} value to a Vortex scalar"),
         }
     }


Reviews:
user: login: 0ax1
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-02T14:33:07Z
user: login: joseph-isaacs
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-02T14:41:39Z
user: login: joseph-isaacs
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-02T14:41:54Z
user: login: 0ax1
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-02T14:51:47Z

Review comments:
diff_hunk: @@ -72,7 +92,7 @@ pub async fn load_datasets(
             Format::OnDiskVortex => {
                 register_vortex_file(&context, object_store.clone(), name, &path, schema).await?
             }
-            Format::OnDiskDuckDB => todo!(),
+            Format::OnDiskDuckDB => unreachable!("duckdb never supported with datafusionn"),
path: bench-vortex/src/tpch/mod.rs
user: login: 0ax1
body: `datafusionn` => `datafusion`
created_at: 2025-05-02T14:00:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -205,9 +203,31 @@ async fn bench_main(
                     progress.inc(1);
                 }
             }
-            _ => {
-                warn!("Engine {:?} not supported for TPC-H benchmarks", engine);
+            Engine::DataFusion => {
+                if false {
+                    todo!("add schemas for tpcds")
path: bench-vortex/src/bin/tpcds.rs
user: login: 0ax1
body: What's this todo style about? Why not `// TODO: ..`?
created_at: 2025-05-02T14:01:25Z
author_association: CONTRIBUTOR
diff_hunk: @@ -208,7 +208,14 @@ fn main() -> anyhow::Result<()> {
         .targets
         .iter()
         .any(|t| t.engine() == Engine::DuckDB)
-        .then(|| ddb::build_and_get_executable_path(&args.duckdb_path, false));
+        .then(|| {
+            let path = ddb::get_executable_path(&args.duckdb_path);
+            // If the path is to vortex duckdb, try to rebuild
+            if args.duckdb_path.is_none() {
+                ddb::build_executable_path();
path: bench-vortex/src/bin/clickbench.rs
user: login: 0ax1
body: We just build DuckDB here, right? Probably `build_executable_path` should be renamed to `build_duckdb` or so.
created_at: 2025-05-02T14:07:17Z
author_association: CONTRIBUTOR
diff_hunk: @@ -208,7 +208,14 @@ fn main() -> anyhow::Result<()> {
         .targets
         .iter()
         .any(|t| t.engine() == Engine::DuckDB)
-        .then(|| ddb::build_and_get_executable_path(&args.duckdb_path, false));
+        .then(|| {
+            let path = ddb::get_executable_path(&args.duckdb_path);
+            // If the path is to vortex duckdb, try to rebuild
path: bench-vortex/src/bin/clickbench.rs
user: login: 0ax1
body: I think this comment is a little misleading. It's more like if the path is not set at all.
created_at: 2025-05-02T14:08:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -123,34 +123,34 @@ fn main() -> anyhow::Result<()> {
         _guard
     };
 
+    let formats = args.targets.iter().map(|t| t.format()).collect_vec();
+
     let runtime = new_tokio_runtime(args.threads);
 
+    let duckdb_resolved_path = ddb::get_executable_path(&args.duckdb_path);
+    if args.duckdb_path.is_none() && !args.skip_rebuild {
+        ddb::build_executable_path();
+    }
+
     let url = match args.use_remote_data_dir {
         None => {
-            let data_dir = match args.data_generator {
-                DataGenerator::Dbgen => {
-                    let db_gen_options =
-                        DBGenOptions::default().with_scale_factor(args.scale_factor);
-                    DBGen::new(db_gen_options).generate()?
-                }
-                DataGenerator::Duckdb => todo!("not implemented yet, will be support this soon"),
-                // TODO(joe) re-enable this once its correct.
-                // DataGenerator::Duckdb => {
-                //     generate_tpc(DuckdbTpcOptions::default().with_scale_factor(args.scale_factor))?
-                // }
-            };
+            for format in formats {
+                // Arrow uses csv
+                let format = if format == Format::Arrow {
path: bench-vortex/src/bin/tpch.rs
user: login: 0ax1
body: For patterns like this combinators make the code a bit more compact. Along the lines of 
```
(format == Format::Arrow).then().or()
```
created_at: 2025-05-02T14:11:08Z
author_association: CONTRIBUTOR
diff_hunk: @@ -197,20 +120,18 @@ pub async fn register_vortex_files(
                 file_url,
                 schema,
                 single_file,
-            )?;
+            )
+            .await?;
         }
-        _ => todo!(),
     }
 
     Ok(())
 }
 
+#[allow(dead_code)]
path: bench-vortex/src/datasets/file.rs
user: login: 0ax1
body: `dead_code`?
created_at: 2025-05-02T14:13:18Z
author_association: CONTRIBUTOR
diff_hunk: @@ -183,6 +200,7 @@ fn create_table_registration(
 }
 
 /// Resolves the storage URL based on dataset and format requirements
+#[allow(dead_code)]
path: bench-vortex/src/engines/ddb/mod.rs
user: login: 0ax1
body: ?
created_at: 2025-05-02T14:17:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -40,27 +42,45 @@ pub const EXPECTED_ROW_COUNTS_SF10: [usize; TPC_H_ROW_COUNT_ARRAY_LENGTH] = [
 pub async fn load_datasets(
     base_dir: &Url,
     format: Format,
+    dataset: BenchmarkDataset,
     disable_datafusion_cache: bool,
 ) -> anyhow::Result<SessionContext> {
     let context = get_session_context(disable_datafusion_cache);
 
     let object_store = make_object_store(&context, base_dir)?;
 
-    let files = [
-        ("customer", &schema::CUSTOMER),
-        ("lineitem", &schema::LINEITEM),
-        ("nation", &schema::NATION),
-        ("orders", &schema::ORDERS),
-        ("part", &schema::PART),
-        ("partsupp", &schema::PARTSUPP),
-        ("region", &schema::REGION),
-        ("supplier", &schema::SUPPLIER),
-    ];
-
-    for (name, path, schema) in files
-        .into_iter()
-        .map(|(name, schema)| (name, base_dir.join(&format!("{name}.tbl")), schema))
-    {
+    let files = match dataset {
+        BenchmarkDataset::TpcH => vec![
+            ("customer", Some(schema::CUSTOMER.clone())),
+            ("lineitem", Some(schema::LINEITEM.clone())),
+            ("nation", Some(schema::NATION.clone())),
+            ("orders", Some(schema::ORDERS.clone())),
+            ("part", Some(schema::PART.clone())),
+            ("partsupp", Some(schema::PARTSUPP.clone())),
+            ("region", Some(schema::REGION.clone())),
+            ("supplier", Some(schema::SUPPLIER.clone())),
+        ],
+
+        BenchmarkDataset::TpcDS => BenchmarkDataset::TpcDS
+            .tables()
+            .iter()
+            .map(|f| (*f, None))
+            .collect_vec(),
+        BenchmarkDataset::ClickBench { .. } => todo!(),
+    };
+
+    for (name, path, schema) in files.into_iter().map(|(name, schema)| {
+        let format = if format == Format::Arrow {
path: bench-vortex/src/tpch/mod.rs
user: login: 0ax1
body: Consider a combinator with .then.else
created_at: 2025-05-02T14:30:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -72,7 +92,7 @@ pub async fn load_datasets(
             Format::OnDiskVortex => {
                 register_vortex_file(&context, object_store.clone(), name, &path, schema).await?
             }
-            Format::OnDiskDuckDB => todo!(),
+            Format::OnDiskDuckDB => unreachable!("duckdb never supported with datafusionn"),
path: bench-vortex/src/tpch/mod.rs
user: login: joseph-isaacs
body: ```suggestion
            Format::OnDiskDuckDB => unreachable!("duckdb never supported with datafusion"),
```
created_at: 2025-05-02T14:41:33Z
author_association: CONTRIBUTOR
diff_hunk: @@ -40,27 +42,45 @@ pub const EXPECTED_ROW_COUNTS_SF10: [usize; TPC_H_ROW_COUNT_ARRAY_LENGTH] = [
 pub async fn load_datasets(
     base_dir: &Url,
     format: Format,
+    dataset: BenchmarkDataset,
     disable_datafusion_cache: bool,
 ) -> anyhow::Result<SessionContext> {
     let context = get_session_context(disable_datafusion_cache);
 
     let object_store = make_object_store(&context, base_dir)?;
 
-    let files = [
-        ("customer", &schema::CUSTOMER),
-        ("lineitem", &schema::LINEITEM),
-        ("nation", &schema::NATION),
-        ("orders", &schema::ORDERS),
-        ("part", &schema::PART),
-        ("partsupp", &schema::PARTSUPP),
-        ("region", &schema::REGION),
-        ("supplier", &schema::SUPPLIER),
-    ];
-
-    for (name, path, schema) in files
-        .into_iter()
-        .map(|(name, schema)| (name, base_dir.join(&format!("{name}.tbl")), schema))
-    {
+    let files = match dataset {
+        BenchmarkDataset::TpcH => vec![
+            ("customer", Some(schema::CUSTOMER.clone())),
+            ("lineitem", Some(schema::LINEITEM.clone())),
+            ("nation", Some(schema::NATION.clone())),
+            ("orders", Some(schema::ORDERS.clone())),
+            ("part", Some(schema::PART.clone())),
+            ("partsupp", Some(schema::PARTSUPP.clone())),
+            ("region", Some(schema::REGION.clone())),
+            ("supplier", Some(schema::SUPPLIER.clone())),
+        ],
+
+        BenchmarkDataset::TpcDS => BenchmarkDataset::TpcDS
+            .tables()
+            .iter()
+            .map(|f| (*f, None))
+            .collect_vec(),
+        BenchmarkDataset::ClickBench { .. } => todo!(),
+    };
+
+    for (name, path, schema) in files.into_iter().map(|(name, schema)| {
+        let format = if format == Format::Arrow {
path: bench-vortex/src/tpch/mod.rs
user: login: joseph-isaacs
body: clippy doesnt like it 😢 
created_at: 2025-05-02T14:41:54Z
author_association: CONTRIBUTOR

PR comments:
user: login: github-actions[bot]
created_at: 2025-05-01T15:46:06Z
body: # Benchmarks: random_access
<details>
<summary>Table of Results</summary>

| name                                   |   PR 8e9a6872 |   base 37f37f56 |   ratio (PR/base) | unit   |
|:---------------------------------------|--------------:|----------------:|------------------:|:-------|
| random-access/vortex-tokio-local-disk  |       1584339 |     1.75842e+06 |          0.901003 | ns     |
| random-access/parquet-tokio-local-disk |     189250779 |     1.8034e+08  |          1.04941  | ns     |
</details>

<!-- thollander/actions-comment-pull-request "bench-pr-comment-random_access" -->
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-05-01T16:10:38Z
body: # Benchmarks: Clickbench on NVME
<details>
<summary>Table of Results</summary>

| name                                             |   PR 8e9a6872 |   base 37f37f56 |   ratio (PR/base) | unit   |
|:-------------------------------------------------|--------------:|----------------:|------------------:|:-------|
| clickbench_q00/DataFusion:parquet                |       1309810 |     1.28589e+06 |          1.0186   | ns     |
| clickbench_q01/DataFusion:parquet                |      28988752 |     2.80894e+07 |          1.03202  | ns     |
| clickbench_q02/DataFusion:parquet                |      67023085 |     6.55422e+07 |          1.02259  | ns     |
| clickbench_q03/DataFusion:parquet                |      55882983 |     5.26754e+07 |          1.06089  | ns     |
| clickbench_q04/DataFusion:parquet                |     411206783 |     3.97684e+08 |          1.034    | ns     |
| clickbench_q05/DataFusion:parquet                |     387970451 |     3.81185e+08 |          1.0178   | ns     |
| clickbench_q06/DataFusion:parquet                |       1308118 |     1.38829e+06 |          0.942249 | ns     |
| clickbench_q07/DataFusion:parquet                |      31844366 |     3.08564e+07 |          1.03202  | ns     |
| clickbench_q08/DataFusion:parquet                |     469218028 |     4.50033e+08 |          1.04263  | ns     |
| clickbench_q09/DataFusion:parquet                |     694775097 |     6.82919e+08 |          1.01736  | ns     |
| clickbench_q10/DataFusion:parquet                |     149132148 |     1.44616e+08 |          1.03123  | ns     |
| clickbench_q11/DataFusion:parquet                |     180269736 |     1.76138e+08 |          1.02346  | ns     |
| clickbench_q12/DataFusion:parquet                |     415366161 |     4.05937e+08 |          1.02323  | ns     |
| clickbench_q13/DataFusion:parquet                |     583328809 |     5.70767e+08 |          1.02201  | ns     |
| clickbench_q14/DataFusion:parquet                |     402924556 |     3.87559e+08 |          1.03965  | ns     |
| clickbench_q15/DataFusion:parquet                |     482239628 |     4.62519e+08 |          1.04264  | ns     |
| clickbench_q16/DataFusion:parquet                |     833728024 |     8.10268e+08 |          1.02895  | ns     |
| clickbench_q17/DataFusion:parquet                |     809204698 |     7.89529e+08 |          1.02492  | ns     |
| clickbench_q18/DataFusion:parquet                |    1578448849 |     1.53138e+09 |          1.03074  | ns     |
| clickbench_q19/DataFusion:parquet                |      43078866 |     4.21364e+07 |          1.02237  | ns     |
| clickbench_q20/DataFusion:parquet                |     669176156 |     6.74662e+08 |          0.991869 | ns     |
| clickbench_q21/DataFusion:parquet                |     756179888 |     7.43976e+08 |          1.0164   | ns     |
| clickbench_q22/DataFusion:parquet                |    1195473271 |     1.1863e+09  |          1.00773  | ns     |
| clickbench_q23/DataFusion:parquet                |    5038892821 |     4.91266e+09 |          1.02569  | ns     |
| clickbench_q24/DataFusion:parquet                |     255515463 |     2.4667e+08  |          1.03586  | ns     |
| clickbench_q25/DataFusion:parquet                |     207311403 |     2.10077e+08 |          0.986837 | ns     |
| clickbench_q26/DataFusion:parquet                |     284261054 |     2.73559e+08 |          1.03912  | ns     |
| clickbench_q27/DataFusion:parquet                |     990408865 |     9.57341e+08 |          1.03454  | ns     |
| clickbench_q28/DataFusion:parquet                |    5866779766 |     5.86562e+09 |          1.0002   | ns     |
| clickbench_q29/DataFusion:parquet                |     239419238 |     2.37042e+08 |          1.01003  | ns     |
| clickbench_q30/DataFusion:parquet                |     398057673 |     3.90598e+08 |          1.0191   | ns     |
| clickbench_q31/DataFusion:parquet                |     451514496 |     4.33809e+08 |          1.04081  | ns     |
| clickbench_q32/DataFusion:parquet                |    1452560010 |     1.35039e+09 |          1.07566  | ns     |
| clickbench_q33/DataFusion:parquet                |    1759483802 |     1.67215e+09 |          1.05223  | ns     |
| clickbench_q34/DataFusion:parquet                |    1823589962 |     1.70691e+09 |          1.06836  | ns     |
| clickbench_q35/DataFusion:parquet                |     661645967 |     6.1866e+08  |          1.06948  | ns     |
| clickbench_q36/DataFusion:parquet                |     185063699 |     1.6918e+08  |          1.09388  | ns     |
| clickbench_q37/DataFusion:parquet                |      74000392 |     7.01956e+07 |          1.0542   | ns     |
| clickbench_q38/DataFusion:parquet                |     118193020 |     9.71533e+07 |          1.21656  | ns     |
| clickbench_q39/DataFusion:parquet                |     358611725 |     3.33962e+08 |          1.07381  | ns     |
| clickbench_q40/DataFusion:parquet                |      44570834 |     4.2581e+07  |          1.04673  | ns     |
| clickbench_q41/DataFusion:parquet                |      39685572 |     3.85104e+07 |          1.03052  | ns     |
| clickbench_q42/DataFusion:parquet                |      60956270 |     5.83856e+07 |          1.04403  | ns     |
| clickbench_q00/DataFusion:vortex-file-compressed |       1336833 |     1.38502e+06 |          0.96521  | ns     |
| clickbench_q01/DataFusion:vortex-file-compressed |       7660565 |     7.4796e+06  |          1.02419  | ns     |
| clickbench_q02/DataFusion:vortex-file-compressed |      25084375 |     2.55807e+07 |          0.980599 | ns     |
| clickbench_q03/DataFusion:vortex-file-compressed |      38344786 |     3.55112e+07 |          1.07979  | ns     |
| clickbench_q04/DataFusion:vortex-file-compressed |     350556597 |     3.36608e+08 |          1.04144  | ns     |
| clickbench_q05/DataFusion:vortex-file-compressed |     345649655 |     3.32509e+08 |          1.03952  | ns     |
| clickbench_q06/DataFusion:vortex-file-compressed |       1357137 |     1.39867e+06 |          0.970304 | ns     |
| clickbench_q07/DataFusion:vortex-file-compressed |      11293744 |     1.18691e+07 |          0.951522 | ns     |
| clickbench_q08/DataFusion:vortex-file-compressed |     398603675 |     3.84802e+08 |          1.03587  | ns     |
| clickbench_q09/DataFusion:vortex-file-compressed |     568218220 |     5.26439e+08 |          1.07936  | ns     |
| clickbench_q10/DataFusion:vortex-file-compressed |      76514447 |     7.18133e+07 |          1.06546  | ns     |
| clickbench_q11/DataFusion:vortex-file-compressed |      85003460 |     8.23669e+07 |          1.03201  | ns     |
| clickbench_q12/DataFusion:vortex-file-compressed |     305117154 |     2.9413e+08  |          1.03735  | ns     |
| clickbench_q13/DataFusion:vortex-file-compressed |     489738523 |     4.79144e+08 |          1.02211  | ns     |
| clickbench_q14/DataFusion:vortex-file-compressed |     277332596 |     2.76302e+08 |          1.00373  | ns     |
| clickbench_q15/DataFusion:vortex-file-compressed |     414946704 |     3.94668e+08 |          1.05138  | ns     |
| clickbench_q16/DataFusion:vortex-file-compressed |     842912787 |     8.30333e+08 |          1.01515  | ns     |
| clickbench_q17/DataFusion:vortex-file-compressed |     820937374 |     8.00655e+08 |          1.02533  | ns     |
| clickbench_q18/DataFusion:vortex-file-compressed |    1536598958 |     1.50036e+09 |          1.02415  | ns     |
| clickbench_q19/DataFusion:vortex-file-compressed |      13866914 |     1.34068e+07 |          1.03432  | ns     |
| clickbench_q20/DataFusion:vortex-file-compressed |     276502458 |     2.66341e+08 |          1.03815  | ns     |
| clickbench_q21/DataFusion:vortex-file-compressed |     340755677 |     3.29496e+08 |          1.03417  | ns     |
| clickbench_q22/DataFusion:vortex-file-compressed |     702504258 |     6.92911e+08 |          1.01384  | ns     |
| clickbench_q23/DataFusion:vortex-file-compressed |    2029060607 |     2.01223e+09 |          1.00836  | ns     |
| clickbench_q24/DataFusion:vortex-file-compressed |     131420876 |     1.25244e+08 |          1.04931  | ns     |
| clickbench_q25/DataFusion:vortex-file-compressed |      98985978 |     1.07229e+08 |          0.923126 | ns     |
| clickbench_q26/DataFusion:vortex-file-compressed |     160299584 |     1.56008e+08 |          1.02751  | ns     |
| clickbench_q27/DataFusion:vortex-file-compressed |     722541435 |     6.96935e+08 |          1.03674  | ns     |
| clickbench_q28/DataFusion:vortex-file-compressed |    6528542054 |     6.52259e+09 |          1.00091  | ns     |
| clickbench_q29/DataFusion:vortex-file-compressed |     226550865 |     2.42561e+08 |          0.933994 | ns     |
| clickbench_q30/DataFusion:vortex-file-compressed |     253544373 |     2.44813e+08 |          1.03567  | ns     |
| clickbench_q31/DataFusion:vortex-file-compressed |     290987816 |     2.82994e+08 |          1.02825  | ns     |
| clickbench_q32/DataFusion:vortex-file-compressed |    1352604790 |     1.25506e+09 |          1.07773  | ns     |
| clickbench_q33/DataFusion:vortex-file-compressed |    1532797878 |     1.53119e+09 |          1.00105  | ns     |
| clickbench_q34/DataFusion:vortex-file-compressed |    1577787975 |     1.57767e+09 |          1.00007  | ns     |
| clickbench_q35/DataFusion:vortex-file-compressed |     564719991 |     5.44671e+08 |          1.03681  | ns     |
| clickbench_q36/DataFusion:vortex-file-compressed |     107907639 |     9.50854e+07 |          1.13485  | ns     |
| clickbench_q37/DataFusion:vortex-file-compressed |      40058063 |     4.00127e+07 |          1.00113  | ns     |
| clickbench_q38/DataFusion:vortex-file-compressed |      29046455 |     2.63582e+07 |          1.10199  | ns     |
| clickbench_q39/DataFusion:vortex-file-compressed |     194098756 |     1.84095e+08 |          1.05434  | ns     |
| clickbench_q40/DataFusion:vortex-file-compressed |      15493613 |     1.59003e+07 |          0.974424 | ns     |
| clickbench_q41/DataFusion:vortex-file-compressed |      14868000 |     1.43967e+07 |          1.03273  | ns     |
| clickbench_q42/DataFusion:vortex-file-compressed |      37788160 |     3.69671e+07 |          1.02221  | ns     |
| clickbench_q00/DuckDB:parquet                    |     249000000 |     2.43e+08    |          1.02469  | ns     |
| clickbench_q01/DuckDB:parquet                    |     160000000 |     1.57e+08    |          1.01911  | ns     |
| clickbench_q02/DuckDB:parquet                    |     188000000 |     1.83e+08    |          1.02732  | ns     |
| clickbench_q03/DuckDB:parquet                    |     184000000 |     1.79e+08    |          1.02793  | ns     |
| clickbench_q04/DuckDB:parquet                    |     301000000 |     2.97e+08    |          1.01347  | ns     |
| clickbench_q05/DuckDB:parquet                    |     330000000 |     3.29e+08    |          1.00304  | ns     |
| clickbench_q06/DuckDB:parquet                    |     174000000 |     1.72e+08    |          1.01163  | ns     |
| clickbench_q07/DuckDB:parquet                    |     163000000 |     1.61e+08    |          1.01242  | ns     |
| clickbench_q08/DuckDB:parquet                    |     341000000 |     3.34e+08    |          1.02096  | ns     |
| clickbench_q09/DuckDB:parquet                    |     442000000 |     4.43e+08    |          0.997743 | ns     |
| clickbench_q10/DuckDB:parquet                    |     220000000 |     2.26e+08    |          0.973451 | ns     |
| clickbench_q11/DuckDB:parquet                    |     233000000 |     2.3e+08     |          1.01304  | ns     |
| clickbench_q12/DuckDB:parquet                    |     347000000 |     3.44e+08    |          1.00872  | ns     |
| clickbench_q13/DuckDB:parquet                    |     527000000 |     5.19e+08    |          1.01541  | ns     |
| clickbench_q14/DuckDB:parquet                    |     388000000 |     3.84e+08    |          1.01042  | ns     |
| clickbench_q15/DuckDB:parquet                    |     320000000 |     3.14e+08    |          1.01911  | ns     |
| clickbench_q16/DuckDB:parquet                    |     662000000 |     6.51e+08    |          1.0169   | ns     |
| clickbench_q17/DuckDB:parquet                    |     578000000 |     5.67e+08    |          1.0194   | ns     |
| clickbench_q18/DuckDB:parquet                    |    1080000000 |     1.064e+09   |          1.01504  | ns     |
| clickbench_q19/DuckDB:parquet                    |     164000000 |     1.59e+08    |          1.03145  | ns     |
| clickbench_q20/DuckDB:parquet                    |     822000000 |     8.2e+08     |          1.00244  | ns     |
| clickbench_q21/DuckDB:parquet                    |     743000000 |     7.37e+08    |          1.00814  | ns     |
| clickbench_q22/DuckDB:parquet                    |    1195000000 |     1.189e+09   |          1.00505  | ns     |
| clickbench_q23/DuckDB:parquet                    |    2709000000 |     2.698e+09   |          1.00408  | ns     |
| clickbench_q24/DuckDB:parquet                    |     144000000 |     1.43e+08    |          1.00699  | ns     |
| clickbench_q25/DuckDB:parquet                    |     236000000 |     2.3e+08     |          1.02609  | ns     |
| clickbench_q26/DuckDB:parquet                    |     142000000 |     1.44e+08    |          0.986111 | ns     |
| clickbench_q27/DuckDB:parquet                    |     867000000 |     8.64e+08    |          1.00347  | ns     |
| clickbench_q28/DuckDB:parquet                    |    6078000000 |     6.02e+09    |          1.00963  | ns     |
| clickbench_q29/DuckDB:parquet                    |     179000000 |     1.78e+08    |          1.00562  | ns     |
| clickbench_q30/DuckDB:parquet                    |     414000000 |     4.09e+08    |          1.01222  | ns     |
| clickbench_q31/DuckDB:parquet                    |     467000000 |     4.64e+08    |          1.00647  | ns     |
| clickbench_q32/DuckDB:parquet                    |    1132000000 |     1.109e+09   |          1.02074  | ns     |
| clickbench_q33/DuckDB:parquet                    |    1349000000 |     1.321e+09   |          1.0212   | ns     |
| clickbench_q34/DuckDB:parquet                    |    1416000000 |     1.388e+09   |          1.02017  | ns     |
| clickbench_q35/DuckDB:parquet                    |     412000000 |     4.08e+08    |          1.0098   | ns     |
| clickbench_q36/DuckDB:parquet                    |     156000000 |     1.56e+08    |          1        | ns     |
| clickbench_q37/DuckDB:parquet                    |     149000000 |     1.46e+08    |          1.02055  | ns     |
| clickbench_q38/DuckDB:parquet                    |     160000000 |     1.56e+08    |          1.02564  | ns     |
| clickbench_q39/DuckDB:parquet                    |     182000000 |     1.83e+08    |          0.994536 | ns     |
| clickbench_q40/DuckDB:parquet                    |     152000000 |     1.52e+08    |          1        | ns     |
| clickbench_q41/DuckDB:parquet                    |     158000000 |     1.57e+08    |          1.00637  | ns     |
| clickbench_q42/DuckDB:parquet                    |     150000000 |     1.45e+08    |          1.03448  | ns     |
| clickbench_q00/DuckDB:vortex-file-compressed     |      24000000 |     2.2e+07     |          1.09091  | ns     |
| clickbench_q01/DuckDB:vortex-file-compressed     |      28000000 |     2.8e+07     |          1        | ns     |
| clickbench_q02/DuckDB:vortex-file-compressed     |     117000000 |     1.16e+08    |          1.00862  | ns     |
| clickbench_q03/DuckDB:vortex-file-compressed     |      91000000 |     9.7e+07     |          0.938144 | ns     |
| clickbench_q04/DuckDB:vortex-file-compressed     |     277000000 |     2.81e+08    |          0.985765 | ns     |
| clickbench_q05/DuckDB:vortex-file-compressed     |     353000000 |     3.41e+08    |          1.03519  | ns     |
| clickbench_q06/DuckDB:vortex-file-compressed     |      73000000 |     7.5e+07     |          0.973333 | ns     |
| clickbench_q07/DuckDB:vortex-file-compressed     |      37000000 |     3.7e+07     |          1        | ns     |
| clickbench_q08/DuckDB:vortex-file-compressed     |     376000000 |     3.76e+08    |          1        | ns     |
| clickbench_q09/DuckDB:vortex-file-compressed     |     530000000 |     5.36e+08    |          0.988806 | ns     |
| clickbench_q10/DuckDB:vortex-file-compressed     |     145000000 |     1.39e+08    |          1.04317  | ns     |
| clickbench_q11/DuckDB:vortex-file-compressed     |     167000000 |     1.65e+08    |          1.01212  | ns     |
| clickbench_q12/DuckDB:vortex-file-compressed     |     332000000 |     3.21e+08    |          1.03427  | ns     |
| clickbench_q13/DuckDB:vortex-file-compressed     |     541000000 |     5.24e+08    |          1.03244  | ns     |
| clickbench_q14/DuckDB:vortex-file-compressed     |     361000000 |     3.64e+08    |          0.991758 | ns     |
| clickbench_q15/DuckDB:vortex-file-compressed     |     313000000 |     3.15e+08    |          0.993651 | ns     |
| clickbench_q16/DuckDB:vortex-file-compressed     |     785000000 |     7.9e+08     |          0.993671 | ns     |
| clickbench_q17/DuckDB:vortex-file-compressed     |     705000000 |     6.96e+08    |          1.01293  | ns     |
| clickbench_q18/DuckDB:vortex-file-compressed     |    1448000000 |     1.445e+09   |          1.00208  | ns     |
| clickbench_q19/DuckDB:vortex-file-compressed     |     174000000 |     1.7e+08     |          1.02353  | ns     |
| clickbench_q20/DuckDB:vortex-file-compressed     |     684000000 |     6.87e+08    |          0.995633 | ns     |
| clickbench_q21/DuckDB:vortex-file-compressed     |     473000000 |     4.83e+08    |          0.979296 | ns     |
| clickbench_q22/DuckDB:vortex-file-compressed     |     766000000 |     7.05e+08    |          1.08652  | ns     |
| clickbench_q23/DuckDB:vortex-file-compressed     |    1482000000 |     1.434e+09   |          1.03347  | ns     |
| clickbench_q24/DuckDB:vortex-file-compressed     |     218000000 |     2.17e+08    |          1.00461  | ns     |
| clickbench_q25/DuckDB:vortex-file-compressed     |     173000000 |     1.72e+08    |          1.00581  | ns     |
| clickbench_q26/DuckDB:vortex-file-compressed     |     209000000 |     2.11e+08    |          0.990521 | ns     |
| clickbench_q27/DuckDB:vortex-file-compressed     |     942000000 |     9.4e+08     |          1.00213  | ns     |
| clickbench_q28/DuckDB:vortex-file-compressed     |    6974000000 |     6.988e+09   |          0.997997 | ns     |
| clickbench_q29/DuckDB:vortex-file-compressed     |      87000000 |     8.4e+07     |          1.03571  | ns     |
| clickbench_q30/DuckDB:vortex-file-compressed     |     325000000 |     3.2e+08     |          1.01562  | ns     |
| clickbench_q31/DuckDB:vortex-file-compressed     |     424000000 |     4.52e+08    |          0.938053 | ns     |
| clickbench_q32/DuckDB:vortex-file-compressed     |    1404000000 |     1.353e+09   |          1.03769  | ns     |
| clickbench_q33/DuckDB:vortex-file-compressed     |    1504000000 |     1.438e+09   |          1.0459   | ns     |
| clickbench_q34/DuckDB:vortex-file-compressed     |    1674000000 |     1.632e+09   |          1.02574  | ns     |
| clickbench_q35/DuckDB:vortex-file-compressed     |     461000000 |     4.57e+08    |          1.00875  | ns     |
| clickbench_q36/DuckDB:vortex-file-compressed     |      85000000 |     8.3e+07     |          1.0241   | ns     |
| clickbench_q37/DuckDB:vortex-file-compressed     |      40000000 |     3.7e+07     |          1.08108  | ns     |
| clickbench_q38/DuckDB:vortex-file-compressed     |      55000000 |     5.2e+07     |          1.05769  | ns     |
| clickbench_q39/DuckDB:vortex-file-compressed     |     175000000 |     1.74e+08    |          1.00575  | ns     |
| clickbench_q40/DuckDB:vortex-file-compressed     |      29000000 |     3e+07       |          0.966667 | ns     |
| clickbench_q41/DuckDB:vortex-file-compressed     |      31000000 |     3e+07       |          1.03333  | ns     |
| clickbench_q42/DuckDB:vortex-file-compressed     |      33000000 |     3.6e+07     |          0.916667 | ns     |
| clickbench_q00/DuckDB:duckdb                     |      18000000 |     1.8e+07     |          1        | ns     |
| clickbench_q01/DuckDB:duckdb                     |      37000000 |     3.6e+07     |          1.02778  | ns     |
| clickbench_q02/DuckDB:duckdb                     |      71000000 |     6.8e+07     |          1.04412  | ns     |
| clickbench_q03/DuckDB:duckdb                     |      63000000 |     6.2e+07     |          1.01613  | ns     |
| clickbench_q04/DuckDB:duckdb                     |     232000000 |     2.29e+08    |          1.0131   | ns     |
| clickbench_q05/DuckDB:duckdb                     |     314000000 |     3.15e+08    |          0.996825 | ns     |
| clickbench_q06/DuckDB:duckdb                     |      40000000 |     4e+07       |          1        | ns     |
| clickbench_q07/DuckDB:duckdb                     |      37000000 |     3.8e+07     |          0.973684 | ns     |
| clickbench_q08/DuckDB:duckdb                     |     278000000 |     2.79e+08    |          0.996416 | ns     |
| clickbench_q09/DuckDB:duckdb                     |     386000000 |     3.81e+08    |          1.01312  | ns     |
| clickbench_q10/DuckDB:duckdb                     |     125000000 |     1.24e+08    |          1.00806  | ns     |
| clickbench_q11/DuckDB:duckdb                     |     141000000 |     1.4e+08     |          1.00714  | ns     |
| clickbench_q12/DuckDB:duckdb                     |     291000000 |     2.89e+08    |          1.00692  | ns     |
| clickbench_q13/DuckDB:duckdb                     |     476000000 |     4.7e+08     |          1.01277  | ns     |
| clickbench_q14/DuckDB:duckdb                     |     316000000 |     3.18e+08    |          0.993711 | ns     |
| clickbench_q15/DuckDB:duckdb                     |     261000000 |     2.57e+08    |          1.01556  | ns     |
| clickbench_q16/DuckDB:duckdb                     |     636000000 |     6.23e+08    |          1.02087  | ns     |
| clickbench_q17/DuckDB:duckdb                     |     542000000 |     5.42e+08    |          1        | ns     |
| clickbench_q18/DuckDB:duckdb                     |    1074000000 |     1.06e+09    |          1.01321  | ns     |
| clickbench_q19/DuckDB:duckdb                     |      36000000 |     3.5e+07     |          1.02857  | ns     |
| clickbench_q20/DuckDB:duckdb                     |     672000000 |     6.42e+08    |          1.04673  | ns     |
| clickbench_q21/DuckDB:duckdb                     |     550000000 |     5.37e+08    |          1.02421  | ns     |
| clickbench_q22/DuckDB:duckdb                     |     832000000 |     8.18e+08    |          1.01711  | ns     |
| clickbench_q23/DuckDB:duckdb                     |     343000000 |     3.27e+08    |          1.04893  | ns     |
| clickbench_q24/DuckDB:duckdb                     |      60000000 |     6e+07       |          1        | ns     |
| clickbench_q25/DuckDB:duckdb                     |     130000000 |     1.28e+08    |          1.01562  | ns     |
| clickbench_q26/DuckDB:duckdb                     |      58000000 |     5.9e+07     |          0.983051 | ns     |
| clickbench_q27/DuckDB:duckdb                     |     658000000 |     6.46e+08    |          1.01858  | ns     |
| clickbench_q28/DuckDB:duckdb                     |    5920000000 |     5.877e+09   |          1.00732  | ns     |
| clickbench_q29/DuckDB:duckdb                     |      60000000 |     5.9e+07     |          1.01695  | ns     |
| clickbench_q30/DuckDB:duckdb                     |     316000000 |     3.14e+08    |          1.00637  | ns     |
| clickbench_q31/DuckDB:duckdb                     |     409000000 |     4e+08       |          1.0225   | ns     |
| clickbench_q32/DuckDB:duckdb                     |    1122000000 |     1.101e+09   |          1.01907  | ns     |
| clickbench_q33/DuckDB:duckdb                     |    1358000000 |     1.309e+09   |          1.03743  | ns     |
| clickbench_q34/DuckDB:duckdb                     |    1385000000 |     1.342e+09   |          1.03204  | ns     |
| clickbench_q35/DuckDB:duckdb                     |     305000000 |     3.21e+08    |          0.950156 | ns     |
| clickbench_q36/DuckDB:duckdb                     |      51000000 |     5.2e+07     |          0.980769 | ns     |
| clickbench_q37/DuckDB:duckdb                     |      38000000 |     3.3e+07     |          1.15152  | ns     |
| clickbench_q38/DuckDB:duckdb                     |      35000000 |     3.4e+07     |          1.02941  | ns     |
| clickbench_q39/DuckDB:duckdb                     |      76000000 |     7.6e+07     |          1        | ns     |
| clickbench_q40/DuckDB:duckdb                     |      33000000 |     3.3e+07     |          1        | ns     |
| clickbench_q41/DuckDB:duckdb                     |      33000000 |     3.3e+07     |          1        | ns     |
| clickbench_q42/DuckDB:duckdb                     |      33000000 |     3.2e+07     |          1.03125  | ns     |
</details>

<!-- thollander/actions-comment-pull-request "bench-pr-comment-clickbench-nvme" -->
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-05-02T11:48:06Z
body: # Benchmarks: TPC-H on NVME
<details>
<summary>Table of Results</summary>

| name                                       |   PR 8e9a6872 |   base 37f37f56 |   ratio (PR/base) | unit   |
|:-------------------------------------------|--------------:|----------------:|------------------:|:-------|
| tpch_q01/DataFusion:arrow                  |      65398860 |     4.59935e+07 |          1.42192  | ns     |
| tpch_q02/DataFusion:arrow                  |      16579996 |     1.62224e+07 |          1.02204  | ns     |
| tpch_q03/DataFusion:arrow                  |      24031980 |     2.05661e+07 |          1.16852  | ns     |
| tpch_q04/DataFusion:arrow                  |      18946127 |     1.88732e+07 |          1.00386  | ns     |
| tpch_q05/DataFusion:arrow                  |      32644380 |     2.98471e+07 |          1.09372  | ns     |
| tpch_q06/DataFusion:arrow                  |       6315441 |     5.04647e+06 |          1.25146  | ns     |
| tpch_q07/DataFusion:arrow                  |      52893012 |     4.70801e+07 |          1.12347  | ns     |
| tpch_q08/DataFusion:arrow                  |      19308101 |     2.02173e+07 |          0.955029 | ns     |
| tpch_q09/DataFusion:arrow                  |      34567772 |     3.0348e+07  |          1.13905  | ns     |
| tpch_q10/DataFusion:arrow                  |      39142765 |     3.68174e+07 |          1.06316  | ns     |
| tpch_q11/DataFusion:arrow                  |       7860808 |     7.57162e+06 |          1.03819  | ns     |
| tpch_q12/DataFusion:arrow                  |      18641533 |     1.76262e+07 |          1.0576   | ns     |
| tpch_q13/DataFusion:arrow                  |      14745203 |     1.49558e+07 |          0.985917 | ns     |
| tpch_q14/DataFusion:arrow                  |       8452755 |     7.5476e+06  |          1.11993  | ns     |
| tpch_q15/DataFusion:arrow                  |      18363772 |     1.67246e+07 |          1.09801  | ns     |
| tpch_q16/DataFusion:arrow                  |      14777710 |     1.52888e+07 |          0.966574 | ns     |
| tpch_q17/DataFusion:arrow                  |      49692812 |     4.60908e+07 |          1.07815  | ns     |
| tpch_q18/DataFusion:arrow                  |     108028468 |     9.50304e+07 |          1.13678  | ns     |
| tpch_q19/DataFusion:arrow                  |      17537089 |     1.53256e+07 |          1.1443   | ns     |
| tpch_q20/DataFusion:arrow                  |      24682108 |     2.31411e+07 |          1.06659  | ns     |
| tpch_q21/DataFusion:arrow                  |      83863845 |     8.46126e+07 |          0.991151 | ns     |
| tpch_q22/DataFusion:arrow                  |      10583174 |     1.06954e+07 |          0.989505 | ns     |
| tpch_q01/DataFusion:parquet                |     104298999 |     1.40786e+08 |          0.740831 | ns     |
| tpch_q02/DataFusion:parquet                |      52800879 |     8.66329e+07 |          0.609479 | ns     |
| tpch_q03/DataFusion:parquet                |      49148527 |     9.72169e+07 |          0.505555 | ns     |
| tpch_q04/DataFusion:parquet                |      30962493 |     6.76939e+07 |          0.457389 | ns     |
| tpch_q05/DataFusion:parquet                |      63709744 |     1.06422e+08 |          0.598649 | ns     |
| tpch_q06/DataFusion:parquet                |      28088093 |     2.99394e+07 |          0.938166 | ns     |
| tpch_q07/DataFusion:parquet                |      80979536 |     1.2489e+08  |          0.648405 | ns     |
| tpch_q08/DataFusion:parquet                |      65095873 |     1.19477e+08 |          0.544839 | ns     |
| tpch_q09/DataFusion:parquet                |      84839444 |     1.62529e+08 |          0.521997 | ns     |
| tpch_q10/DataFusion:parquet                |      94729547 |     1.47246e+08 |          0.643344 | ns     |
| tpch_q11/DataFusion:parquet                |      29294710 |     4.2292e+07  |          0.692677 | ns     |
| tpch_q12/DataFusion:parquet                |      40440221 |     8.2181e+07  |          0.492087 | ns     |
| tpch_q13/DataFusion:parquet                |      41514375 |     1.8992e+08  |          0.218589 | ns     |
| tpch_q14/DataFusion:parquet                |      32844006 |     5.11384e+07 |          0.642258 | ns     |
| tpch_q15/DataFusion:parquet                |      54552652 |     7.07865e+07 |          0.770665 | ns     |
| tpch_q16/DataFusion:parquet                |      35472907 |     4.40873e+07 |          0.804606 | ns     |
| tpch_q17/DataFusion:parquet                |      95598512 |     1.23224e+08 |          0.775812 | ns     |
| tpch_q18/DataFusion:parquet                |     116484489 |     2.15972e+08 |          0.539351 | ns     |
| tpch_q19/DataFusion:parquet                |      72755373 |     8.33511e+07 |          0.872878 | ns     |
| tpch_q20/DataFusion:parquet                |      58926073 |     8.72017e+07 |          0.675744 | ns     |
| tpch_q21/DataFusion:parquet                |     103805356 |     1.72417e+08 |          0.602059 | ns     |
| tpch_q22/DataFusion:parquet                |      50786785 |     5.08448e+07 |          0.998859 | ns     |
| tpch_q01/DataFusion:vortex-file-compressed |      61232951 |     4.00946e+07 |          1.52721  | ns     |
| tpch_q02/DataFusion:vortex-file-compressed |      39843850 |     3.92597e+07 |          1.01488  | ns     |
| tpch_q03/DataFusion:vortex-file-compressed |      31625061 |     2.73685e+07 |          1.15553  | ns     |
| tpch_q04/DataFusion:vortex-file-compressed |      15957161 |     1.65597e+07 |          0.963614 | ns     |
| tpch_q05/DataFusion:vortex-file-compressed |      48929936 |     3.88066e+07 |          1.26087  | ns     |
| tpch_q06/DataFusion:vortex-file-compressed |       4570611 |     8.03067e+06 |          0.569145 | ns     |
| tpch_q07/DataFusion:vortex-file-compressed |      65368061 |     5.74746e+07 |          1.13734  | ns     |
| tpch_q08/DataFusion:vortex-file-compressed |      53928341 |     4.67271e+07 |          1.15411  | ns     |
| tpch_q09/DataFusion:vortex-file-compressed |      75755993 |     5.92345e+07 |          1.27892  | ns     |
| tpch_q10/DataFusion:vortex-file-compressed |      46210123 |     4.3517e+07  |          1.06189  | ns     |
| tpch_q11/DataFusion:vortex-file-compressed |      26218884 |     1.95076e+07 |          1.34404  | ns     |
| tpch_q12/DataFusion:vortex-file-compressed |      18170568 |     1.98468e+07 |          0.91554  | ns     |
| tpch_q13/DataFusion:vortex-file-compressed |      18885213 |     1.91509e+07 |          0.986124 | ns     |
| tpch_q14/DataFusion:vortex-file-compressed |      12452346 |     1.11094e+07 |          1.12089  | ns     |
| tpch_q15/DataFusion:vortex-file-compressed |      22576575 |     1.96985e+07 |          1.1461   | ns     |
| tpch_q16/DataFusion:vortex-file-compressed |      22956933 |     2.29628e+07 |          0.999746 | ns     |
| tpch_q17/DataFusion:vortex-file-compressed |      79005916 |     6.26553e+07 |          1.26096  | ns     |
| tpch_q18/DataFusion:vortex-file-compressed |      94825478 |     9.80435e+07 |          0.967177 | ns     |
| tpch_q19/DataFusion:vortex-file-compressed |      18603818 |     2.47861e+07 |          0.750574 | ns     |
| tpch_q20/DataFusion:vortex-file-compressed |      28447264 |     2.67719e+07 |          1.06258  | ns     |
| tpch_q21/DataFusion:vortex-file-compressed |      87285641 |     9.08158e+07 |          0.961129 | ns     |
| tpch_q22/DataFusion:vortex-file-compressed |      12947157 |     1.32776e+07 |          0.975109 | ns     |
| tpch_q01/DuckDB:parquet                    |      62000000 |     9e+07       |          0.688889 | ns     |
| tpch_q02/DuckDB:parquet                    |      36000000 |     7.4e+07     |          0.486486 | ns     |
| tpch_q03/DuckDB:parquet                    |      80000000 |     1.56e+08    |          0.512821 | ns     |
| tpch_q04/DuckDB:parquet                    |      38000000 |     9.3e+07     |          0.408602 | ns     |
| tpch_q05/DuckDB:parquet                    |      58000000 |     1.26e+08    |          0.460317 | ns     |
| tpch_q06/DuckDB:parquet                    |      31000000 |     4.4e+07     |          0.704545 | ns     |
| tpch_q07/DuckDB:parquet                    |      58000000 |     1.2e+08     |          0.483333 | ns     |
| tpch_q08/DuckDB:parquet                    |      68000000 |     1.54e+08    |          0.441558 | ns     |
| tpch_q09/DuckDB:parquet                    |      96000000 |     1.7e+08     |          0.564706 | ns     |
| tpch_q10/DuckDB:parquet                    |     329000000 |     4.08e+08    |          0.806373 | ns     |
| tpch_q11/DuckDB:parquet                    |      18000000 |     3.7e+07     |          0.486486 | ns     |
| tpch_q12/DuckDB:parquet                    |      46000000 |     9e+07       |          0.511111 | ns     |
| tpch_q13/DuckDB:parquet                    |      56000000 |     3.02e+08    |          0.18543  | ns     |
| tpch_q14/DuckDB:parquet                    |      50000000 |     7.8e+07     |          0.641026 | ns     |
| tpch_q15/DuckDB:parquet                    |      64000000 |     5.4e+07     |          1.18519  | ns     |
| tpch_q16/DuckDB:parquet                    |      68000000 |     1.02e+08    |          0.666667 | ns     |
| tpch_q17/DuckDB:parquet                    |      61000000 |     8.7e+07     |          0.701149 | ns     |
| tpch_q18/DuckDB:parquet                    |      76000000 |     1.4e+08     |          0.542857 | ns     |
| tpch_q19/DuckDB:parquet                    |      71000000 |     1e+08       |          0.71     | ns     |
| tpch_q20/DuckDB:parquet                    |      61000000 |     1.1e+08     |          0.554545 | ns     |
| tpch_q21/DuckDB:parquet                    |     116000000 |     1.83e+08    |          0.63388  | ns     |
| tpch_q22/DuckDB:parquet                    |      45000000 |     7.4e+07     |          0.608108 | ns     |
| tpch_q01/DuckDB:vortex-file-compressed     |     310000000 |     3.14e+08    |          0.987261 | ns     |
| tpch_q02/DuckDB:vortex-file-compressed     |      86000000 |     9.3e+07     |          0.924731 | ns     |
| tpch_q03/DuckDB:vortex-file-compressed     |     269000000 |     2.97e+08    |          0.905724 | ns     |
| tpch_q04/DuckDB:vortex-file-compressed     |     159000000 |     2e+08       |          0.795    | ns     |
| tpch_q05/DuckDB:vortex-file-compressed     |     391000000 |     4.53e+08    |          0.863135 | ns     |
| tpch_q06/DuckDB:vortex-file-compressed     |       6000000 |     5.4e+07     |          0.111111 | ns     |
| tpch_q07/DuckDB:vortex-file-compressed     |     196000000 |     2.29e+08    |          0.855895 | ns     |
| tpch_q08/DuckDB:vortex-file-compressed     |     421000000 |     4.7e+08     |          0.895745 | ns     |
| tpch_q09/DuckDB:vortex-file-compressed     |     789000000 |     9.31e+08    |          0.847476 | ns     |
| tpch_q10/DuckDB:vortex-file-compressed     |     400000000 |     4.3e+08     |          0.930233 | ns     |
| tpch_q11/DuckDB:vortex-file-compressed     |      65000000 |     6.3e+07     |          1.03175  | ns     |
| tpch_q12/DuckDB:vortex-file-compressed     |     174000000 |     2.29e+08    |          0.759825 | ns     |
| tpch_q13/DuckDB:vortex-file-compressed     |     281000000 |     2.79e+08    |          1.00717  | ns     |
| tpch_q14/DuckDB:vortex-file-compressed     |      54000000 |     6.8e+07     |          0.794118 | ns     |
| tpch_q15/DuckDB:vortex-file-compressed     |      55000000 |     6.5e+07     |          0.846154 | ns     |
| tpch_q16/DuckDB:vortex-file-compressed     |     114000000 |     1.15e+08    |          0.991304 | ns     |
| tpch_q17/DuckDB:vortex-file-compressed     |     109000000 |     1.28e+08    |          0.851562 | ns     |
| tpch_q18/DuckDB:vortex-file-compressed     |     333000000 |     3.21e+08    |          1.03738  | ns     |
| tpch_q19/DuckDB:vortex-file-compressed     |     121000000 |     1.29e+08    |          0.937984 | ns     |
| tpch_q20/DuckDB:vortex-file-compressed     |     120000000 |     1.22e+08    |          0.983607 | ns     |
| tpch_q21/DuckDB:vortex-file-compressed     |     575000000 |     6.97e+08    |          0.824964 | ns     |
| tpch_q22/DuckDB:vortex-file-compressed     |      55000000 |     5.6e+07     |          0.982143 | ns     |
| tpch_q01/DuckDB:duckdb                     |      26000000 |     2.7e+07     |          0.962963 | ns     |
| tpch_q02/DuckDB:duckdb                     |      21000000 |     2.3e+07     |          0.913043 | ns     |
| tpch_q03/DuckDB:duckdb                     |      55000000 |     5.5e+07     |          1        | ns     |
| tpch_q04/DuckDB:duckdb                     |      22000000 |     2.5e+07     |          0.88     | ns     |
| tpch_q05/DuckDB:duckdb                     |      33000000 |     3.5e+07     |          0.942857 | ns     |
| tpch_q06/DuckDB:duckdb                     |      10000000 |     1.4e+07     |          0.714286 | ns     |
| tpch_q07/DuckDB:duckdb                     |      33000000 |     3.5e+07     |          0.942857 | ns     |
| tpch_q08/DuckDB:duckdb                     |      32000000 |     3.4e+07     |          0.941176 | ns     |
| tpch_q09/DuckDB:duckdb                     |      67000000 |     7e+07       |          0.957143 | ns     |
| tpch_q10/DuckDB:duckdb                     |     282000000 |     2.8e+08     |          1.00714  | ns     |
| tpch_q11/DuckDB:duckdb                     |      11000000 |     1e+07       |          1.1      | ns     |
| tpch_q12/DuckDB:duckdb                     |      29000000 |     3e+07       |          0.966667 | ns     |
| tpch_q13/DuckDB:duckdb                     |      41000000 |     4.2e+07     |          0.97619  | ns     |
| tpch_q14/DuckDB:duckdb                     |      30000000 |     3.1e+07     |          0.967742 | ns     |
| tpch_q15/DuckDB:duckdb                     |      40000000 |     3.7e+07     |          1.08108  | ns     |
| tpch_q16/DuckDB:duckdb                     |      59000000 |     5.9e+07     |          1        | ns     |
| tpch_q17/DuckDB:duckdb                     |      30000000 |     3.2e+07     |          0.9375   | ns     |
| tpch_q18/DuckDB:duckdb                     |      46000000 |     4.6e+07     |          1        | ns     |
| tpch_q19/DuckDB:duckdb                     |      43000000 |     4.3e+07     |          1        | ns     |
| tpch_q20/DuckDB:duckdb                     |      34000000 |     3.3e+07     |          1.0303   | ns     |
| tpch_q21/DuckDB:duckdb                     |      65000000 |     6.7e+07     |          0.970149 | ns     |
| tpch_q22/DuckDB:duckdb                     |      32000000 |     3.2e+07     |          1        | ns     |
</details>

<!-- thollander/actions-comment-pull-request "bench-pr-comment-tpch-nvme" -->
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-05-02T11:48:39Z
body: # Benchmarks: TPC-H on S3
<details>
<summary>Table of Results</summary>

| name                                       |   PR 8e9a6872 |   base 37f37f56 |   ratio (PR/base) | unit   |
|:-------------------------------------------|--------------:|----------------:|------------------:|:-------|
| tpch_q01/DataFusion:parquet                |     222173553 |     2.97043e+08 |         0.747952  | ns     |
| tpch_q02/DataFusion:parquet                |     789470220 |     7.36656e+08 |         1.07169   | ns     |
| tpch_q03/DataFusion:parquet                |     354059392 |     4.40174e+08 |         0.804362  | ns     |
| tpch_q04/DataFusion:parquet                |     231981483 |     2.57316e+08 |         0.901544  | ns     |
| tpch_q05/DataFusion:parquet                |     543139193 |     5.41609e+08 |         1.00283   | ns     |
| tpch_q06/DataFusion:parquet                |     149294988 |     1.91383e+08 |         0.780086  | ns     |
| tpch_q07/DataFusion:parquet                |     526397118 |     5.86832e+08 |         0.897016  | ns     |
| tpch_q08/DataFusion:parquet                |     764531798 |     7.85304e+08 |         0.973548  | ns     |
| tpch_q09/DataFusion:parquet                |     618175947 |     6.81857e+08 |         0.906607  | ns     |
| tpch_q10/DataFusion:parquet                |     552060282 |     5.90189e+08 |         0.935395  | ns     |
| tpch_q11/DataFusion:parquet                |     484109767 |     3.07155e+08 |         1.57611   | ns     |
| tpch_q12/DataFusion:parquet                |     291415259 |     2.88151e+08 |         1.01133   | ns     |
| tpch_q13/DataFusion:parquet                |     208154362 |     4.415e+08   |         0.471471  | ns     |
| tpch_q14/DataFusion:parquet                |     286782947 |     2.70419e+08 |         1.06051   | ns     |
| tpch_q15/DataFusion:parquet                |     373629751 |     5.10816e+08 |         0.731438  | ns     |
| tpch_q16/DataFusion:parquet                |     371308646 |     2.90405e+08 |         1.27859   | ns     |
| tpch_q17/DataFusion:parquet                |     526262568 |     4.21247e+08 |         1.2493    | ns     |
| tpch_q18/DataFusion:parquet                |     479955673 |     5.75892e+08 |         0.833412  | ns     |
| tpch_q19/DataFusion:parquet                |     380353661 |     3.14738e+08 |         1.20848   | ns     |
| tpch_q20/DataFusion:parquet                |     528938530 |     5.44525e+08 |         0.971377  | ns     |
| tpch_q21/DataFusion:parquet                |     754748073 |     6.85756e+08 |         1.10061   | ns     |
| tpch_q22/DataFusion:parquet                |     286648242 |     2.96589e+08 |         0.966484  | ns     |
| tpch_q01/DataFusion:vortex-file-compressed |     381750666 |     1.45268e+08 |         2.62791   | ns     |
| tpch_q02/DataFusion:vortex-file-compressed |     169867658 |     1.57711e+08 |         1.07708   | ns     |
| tpch_q03/DataFusion:vortex-file-compressed |     347701505 |     2.4073e+08  |         1.44436   | ns     |
| tpch_q04/DataFusion:vortex-file-compressed |     160642668 |     1.55029e+08 |         1.03621   | ns     |
| tpch_q05/DataFusion:vortex-file-compressed |     360290967 |     2.5856e+08  |         1.39345   | ns     |
| tpch_q06/DataFusion:vortex-file-compressed |      10922796 |     1.52702e+08 |         0.0715303 | ns     |
| tpch_q07/DataFusion:vortex-file-compressed |     324884036 |     2.36316e+08 |         1.37479   | ns     |
| tpch_q08/DataFusion:vortex-file-compressed |     353568229 |     3.21475e+08 |         1.09983   | ns     |
| tpch_q09/DataFusion:vortex-file-compressed |     472788981 |     3.08408e+08 |         1.533     | ns     |
| tpch_q10/DataFusion:vortex-file-compressed |     387012823 |     3.01863e+08 |         1.28208   | ns     |
| tpch_q11/DataFusion:vortex-file-compressed |     127563654 |     8.50369e+07 |         1.5001    | ns     |
| tpch_q12/DataFusion:vortex-file-compressed |     204475832 |     1.79983e+08 |         1.13608   | ns     |
| tpch_q13/DataFusion:vortex-file-compressed |     154055887 |     1.43332e+08 |         1.07482   | ns     |
| tpch_q14/DataFusion:vortex-file-compressed |     245508483 |     1.46991e+08 |         1.67022   | ns     |
| tpch_q15/DataFusion:vortex-file-compressed |     420079784 |     2.18924e+08 |         1.91884   | ns     |
| tpch_q16/DataFusion:vortex-file-compressed |      95004223 |     9.33185e+07 |         1.01806   | ns     |
| tpch_q17/DataFusion:vortex-file-compressed |     430448746 |     2.47386e+08 |         1.73999   | ns     |
| tpch_q18/DataFusion:vortex-file-compressed |     435569387 |     2.92216e+08 |         1.49057   | ns     |
| tpch_q19/DataFusion:vortex-file-compressed |      48359367 |     1.70744e+08 |         0.283228  | ns     |
| tpch_q20/DataFusion:vortex-file-compressed |     261695484 |     2.16006e+08 |         1.21152   | ns     |
| tpch_q21/DataFusion:vortex-file-compressed |     380024353 |     3.68942e+08 |         1.03004   | ns     |
| tpch_q22/DataFusion:vortex-file-compressed |     114023860 |     1.14716e+08 |         0.993963  | ns     |
</details>

<!-- thollander/actions-comment-pull-request "bench-pr-comment-tpch-s3" -->
author_association: CONTRIBUTOR