Skip to main content
Version: Next

TPC-DS

TPC-DS is Stroppy's decision-support workload. It generates and loads the 24-table TPC-DS schema and runs the 103-query analytical suite against it.

It models the query load of a retail consolidator: store, web, and catalog sales and returns flowing into fact tables against dimension tables for items, customers, dates, and geography. The workload stresses the same surfaces as TPC-H — scans, multi-table joins, aggregation, sorting, subqueries — but at greater width, with snowflaked dimensions and a far larger, more varied query suite.

Use TPC-DS to evaluate:

  • Bulk load throughput for wide, highly-normalized schemas.
  • Star and snowflake join planning and execution.
  • Aggregation, grouping, sorting, and top-N performance across large fact tables.
  • Window-function and correlated-subquery plans (rank, dense_rank, lag, lead).
  • Planner stability across a varied 100+ query suite.
  • Engine correctness via answer-set validation and cross-database diffing.

Script

TPC-DS has one script: tpcds. PostgreSQL, MySQL, and YDB run the full load + query workload. Picodata is load-only (see Picodata: load-only below): it creates the schema and loads the 24 tables but does not run the query suite.

stroppy run tpcds -d pg -D url=postgres://user:pass@host:5432/bench -e scale_factor=1
stroppy run tpcds -d mysql -D url=root:pass@tcp(host:3306)/bench -e scale_factor=0.1
stroppy run tpcds -d pico -e scale_factor=0.1 --steps drop_schema,create_schema,load_data
stroppy run tpcds -d ydb -D url=grpc://host:2136/database -e scale_factor=0.1

Data Generation

Stroppy generates the dataset itself with a faithful Go port of the official dsdgen, validated byte-for-byte against the reference C generator across all 24 base tables. Generation is parallel and streaming — any table, including the multi-million-row sales and returns fact tables, can be produced in independent partitions with identical output. The workload creates the schema, generates and loads all 24 tables, builds single-table indexes, and runs ANALYZE before the query phase.

SCALE_FACTOR is a fractional row scale. Use 0.1 or 0.01 for smoke tests. Note that some static dimension tables (for example customer_demographics, ~1.9M rows) are fixed-size and do not shrink with the scale factor.

Query Suite

The 103 queries run from per-dialect SQL files generated from the official query templates. PostgreSQL and MySQL run the full suite. YDB runs the baked power test only (see below). Picodata does not run the query workload at all — it is load-only for TPC-DS.

Picodata: load-only

Picodata ships a typed sbroad schema (schema.pico.sql) and loads all 24 tables, but does not run the TPC-DS query suite. Current picodata sbroad cannot parse several constructs the TPC-DS templates use (implicit comma joins such as FROM store_sales, date_dim, among others), so the workload / validate_answers steps abort on the first such query. Run only the load steps against Picodata:

stroppy run tpcds -d pico -e scale_factor=0.1 --steps drop_schema,create_schema,load_data

This makes Picodata usable for TPC-DS bulk-load throughput benchmarks against the wide, snowflaked schema, which is where the driver adds value. Query-suite execution on Picodata is tracked separately and not yet supported.

By default the workload runs the baked canonical query set once (single power-test stream). For a throughput-style run, generate seeded permutations of the query set and drive several concurrent streams:

ENVBehavior
STREAMS=N (N>1)Runs N concurrent VUs, each its own seeded permutation of the queries (throughput test).
QUERY_STREAM=NGenerates query stream N in-process with a fixed seed (single stream).
QUERY_SEEDRNG seed for generated streams.

YDB runs the baked power test only. Setting STREAMS>1 or a non-empty QUERY_STREAM with -d ydb is rejected, because the in-process stream generator cannot target YQL.

Answer Validation

At SCALE_FACTOR=1 on PostgreSQL and MySQL, the workload validates query results against the embedded official SF=1 answer set. Stroppy compares result multisets with numeric tolerance, so engine-specific null and tie ordering is not flagged as a mismatch. Set VALIDATE_FORCE to validate at any scale, and ANSWER_DUMP to dump normalized results to the log for cross-database diffing.

Steps

StepDescription
drop_schemaDrops existing tables (CASCADE), so a re-run against a leftover schema does not fail on dependents.
create_schemaCreates the 24 tables from the dialect schema (schema.pg.sql, schema.mysql.sql, schema.pico.sql, schema.ydb.sql). YDB column mode selects the column-store schema.
set_unloggedPostgreSQL only, when PG_UNLOGGED=true. Flips tables to UNLOGGED before the bulk load.
load_dataGenerates and loads all 24 tables via the native dsdgen path.
create_indexesBuilds single-table indexes after the load so bulk insert is not slowed by index maintenance.
set_loggedPostgreSQL only, when PG_UNLOGGED=true. Flips tables back to LOGGED.
analyzePostgreSQL ANALYZE / MySQL ANALYZE TABLE. No-op on Picodata/YDB.
workloadExecutes the query suite once with pinned parameters and logs per-query duration. Console-silent per iteration. Replaced by validate_answers when validating or dumping.
validate_answersRuns the query suite, captures results, and compares to the SF=1 answer set (PostgreSQL/MySQL at SCALE_FACTOR=1, or when forced). Emits __TPCDS_DUMP__ lines when ANSWER_DUMP is set.

Examples:

stroppy run tpcds -d pg --steps drop_schema,create_schema,load_data
stroppy run tpcds -d pg --steps workload

SQL Files

When SQL_FILE is not set, the script chooses a query file from the active driver type:

Driver typeQuery fileSchema file
postgrestpcds/pg.sqlschema.pg.sql
mysqltpcds/mysql.sqlschema.mysql.sql
picodatatpcds/pico.sqlschema.pico.sql
ydbtpcds/ydb.sqlschema.ydb.sql

Pass an explicit SQL file with SQL_FILE to force a variant:

stroppy run tpcds -d pg -e sql_file=./tpcds/pg.sql

Parameters

Workload parameters are passed as environment variables with -e key=VALUE. Keys are case-insensitive in the CLI.

ParameterDefaultDescription
SCALE_FACTOR1TPC-DS scale factor (fractional).
STREAMS1Concurrent throughput query streams. 1 = single power-test stream.
QUERY_STREAMemptyGenerate query stream N in-process (empty = baked canonical set).
QUERY_SEED19620718RNG seed for generated query streams.
POOL_SIZE50Sets both minConns and maxConns for the primary driver pool.
LOAD_WORKERS0Parallel load workers per table. 0 lets the framework choose.
YDB_STORE_MODEcolumnYDB storage: column (default, OLAP column store) or row.
PG_UNLOGGEDtruePostgreSQL fast bulk-load via UNLOGGED tables, flipped back to LOGGED after load.
SQL_FILEautoQuery SQL file. Defaults to a dialect file based on driverType.
VALIDATE_FORCEemptyForce answer validation at any scale.
ANSWER_DUMPemptyDump normalized query results to the log for cross-database diffing.

TPC-DS queries are read-only and issued outside an explicit transaction; there is no TX_ISOLATION knob.

Metrics

TPC-DS does not define custom k6 Trend or Counter metrics per query. Query timings flow through the common driver metrics during the query phase:

MetricTypeDescription
run_query_countCounterSQL statements executed by the driver.
run_query_durationTrendSQL execution latency samples, tagged by the active step.
run_query_error_rateRateQuery execution failure rate.
insert_durationTrendBulk-load duration samples. Useful for load throughput analysis.
insert_error_rateRateInsert failures during data loading.

For PostgreSQL/MySQL at SCALE_FACTOR=1, validate_answers prints a validation summary against answers_sf1.json, including OK, DIFF, SKIP, and ERROR rows per query.

Thresholds

TPC-DS does not define k6 thresholds by default. The run is not auto-failed by a slow query threshold; correctness is gated by answer-set validation instead.