Changelog
[Unreleased]
Added
- The
columnarinsert method is now accepted by the YDB driver and redirected to the nativeBulkUpsert(already a struct-of-arrays, limit-free payload), logging a one-time warning, instead of being rejected.columnaris now listed for YDB instroppy probe. MySQL and Picodata keep their existing insert methods: on MySQLcolumnarshowed no throughput benefit over multi-rowplain_bulk(measured against TPC-C/H/DS at SF 1), and Picodata's SQL has no array/JSON-expansion path. (#99) - TPC-DS now runs on YDB:
stroppy run tpcds/tpcds -d ydb -D url=grpc://host:2136/database. Ships a typed YQL schema (schema.ydb.sql, column-store default with row-store as an option via-e YDB_STORE_MODE=row) and the 99-query suite ported to YQL (ydb.sql). The loader now feeds YDB's native bulk upsert directly from the generator. Answer-set validation and the in-process query-stream generator stay PostgreSQL/MySQL-only, so YDB runs the baked power test. (#97) stroppy probe(no arguments) now also lists which insert methods each driver supports —plain_query,plain_bulk,columnar,nativeper database — as aDRIVERSblock in the human output and adriverskey in-o json, so external tooling can discover validdefaultInsertMethodvalues per target without reading stroppy source. (#96)
[5.6.0] - 2026-07-01
Added
- New PostgreSQL insert method
columnar: pass one array per column and let the database expand it back to rows (unnest), so a batch binds as many parameters as there are columns instead of rows × columns. This clears PostgreSQL's 65535 bind-parameter limit that plain multi-row inserts hit on wide tables, and loads roughly 2.5–3× faster thanplain_bulk— close toCOPYwhile still being an ordinaryINSERT. Select it with-D defaultInsertMethod=columnar(or"defaultInsertMethod": "columnar"in a driver config). (#93) - Each completed step now reports how long it took, e.g.
End of 'create_schema' step (took 1.23s). (#83) - The
create_indexesandset_loggedsteps now log one progress line per statement, with elapsed time, so you can see which index or table flip is slow instead of waiting on one opaque step boundary. (#83)
Changed
- The per-iteration
workloadstep no longer prints aStart/End of 'workload' stepline on every transaction — that pair was flooding the log. The step still runs and reports its status as before; it is just silent on the console. (#83)
Fixed
- A failed TPC-C
validate_populationcheck now makes the run exit non-zero instead of reporting success. The check detected a bad population and logged every failed assertion, butstroppy runstill exited0, so CI and matrix runs that gate on the exit code saw a false pass. The run now aborts with a dedicated exit code (108) on any population mismatch; a skipped check (--no-steps validate_population) still exits0. (#92)
[5.5.2] - 2026-06-30
Fixed
- Fixed-duration throughput runs (with
DURATIONset) no longer fail to start. The run selects k6's constant-VUs executor, which does not accept themaxDurationoption the workload was still passing, so it aborted at startup withjson: unknown field "maxDuration".maxDurationis now applied only to power tests, where it belongs. (#82) - Power tests with more than one VU (
VUS>1) and the default iteration count no longer fail to start withthe number of iterations can't be less than the number of VUs. The iteration count is now raised to at leastVUS. (#82) - The TPC-DS workload can now be re-run against a database that still holds its schema from a previous run.
drop_schemadrops withCASCADE, so it no longer fails withcannot drop table item because other objects depend on it(SQLSTATE 2BP01). (#82) - The published Docker image (
ghcr.io) builds again. Its build stage used Go 1.25 while the module requires Go 1.26, so image publishing had failed since v5.4.0.
[5.5.1] - 2026-06-29
Fixed
- The default
UNLOGGEDfast bulk-load (PG_UNLOGGED=true) on PostgreSQL no longer fails while preparing TPC-C or TPC-B. PostgreSQL refuses to flip a table toUNLOGGED/LOGGEDwhile it shares a foreign key with a table in the other persistence state (in either direction), so TPC-C errored onset_unlogged(could not change table … because it references logged table …, SQLSTATE 42P16) and TPC-B would hit the same onset_logged. Foreign keys are now created in acreate_foreign_keysstep that runs afterset_logged, once every table is back toLOGGED. The unlogged fast-load path now works for all workloads; previously onlyPG_UNLOGGED=falsesucceeded. Runs that pass an explicitstepsallowlist must addcreate_foreign_keysto it.
[5.5.0] - 2026-06-27
Added
-
All four TPC workloads (B, C, H, DS) now share one consistent lifecycle. Every workload builds its indexes in a dedicated
create_indexesstep after the bulk load and runsANALYZE(analyzestep) so the planner has fresh statistics — previously some workloads built indexes during schema creation, some not at all. On PostgreSQL the bulk load now runs againstUNLOGGEDtables and flips them back toLOGGEDafterwards (set_unlogged/set_loggedsteps) for a much faster, WAL-free load; disable withPG_UNLOGGED=false. -
TPC-C now defines the two spec-permitted secondary indexes (
idx_customer_name,idx_order) on PostgreSQL and MySQL — they serve the mandatory by-last-name customer lookup and the customer's-latest-order path (TPC-C Clause 1.4 / §2.5.2.2 / §2.6.2.2). Previously only the YDB dialect had them. -
Workloads accept unified run knobs:
VUS,DURATION,ITER, andMAX_DURATION. SettingDURATIONruns a fixed-duration throughput test (constant VUs); leaving it unset runs a power test (ITERiterations).MAX_DURATION(default 24h) lifts k6's 10-minute per-iteration cap so large loads never time out. -
TPC-DS data can now be generated by 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/returns fact tables) can be produced in independent partitions with identical output. Thetpcdsworkload now creates the schema and generates/loads all 24 tables itself (create_schema+load_datasteps) before running the query set, mirroring the TPC-H workload; scale viaSCALE_FACTOR. -
The TPC-DS query set now runs on PostgreSQL and MySQL out of the box. The 99 queries ship as per-dialect SQL (
pg.sql,mysql.sql) generated from the official query templates, replacing the old non-portable pre-baked blobs. After loading, the workload builds single-table indexes and runsANALYZEso the heavy queries have usable plans; correlated subqueries that were O(n²) without indexes are pre-aggregated so they stay fast at scale. -
TPC-DS query parameters can be regenerated as seed-reproducible streams of varied-but-valid values (
QUERY_STREAM/QUERY_SEED), and the workload can drive several concurrent query streams (STREAMS), each running its own seeded permutation of the 99 queries — closer to the TPC-DS throughput test. -
TPC-DS results can be validated for correctness: results are checked against the official SF1 answer set, and a cross-database diff tool (
tpcds-diff) compares the same queries run on two engines (e.g. PostgreSQL vs MySQL) using a multiset comparator with numeric tolerance, so engine-specific null/tie ordering isn't flagged as a mismatch. -
TPC-H data is now generated by a faithful port of the official
dbgen, producing correct query answers (validated against the official SF1 answer set) and finalizingo_totalpriceat generation time so no post-load fix-up step is needed. It is also markedly faster — lineitem generation runs several times quicker. Selectable viaTPCH_GENERATOR(gotpcby default,relgenfor the previous generator). (#75) -
Release binaries are now published for arm64 (
aarch64) in addition to x86-64.
Changed
- Data loading moved out of k6's
setup()and into the workload phase for every workload, so load progress now emits live metrics (k6 emits none duringsetup()). The measured workload is a single skippableworkloadstep, which enables a clean two-run flow: load once with--no-steps workload, then measure against the loaded data with--steps workload(the throughput number is then uncontaminated by load time). A normal single run still loads and measures in one pass.
Fixed
-
TPC-B now declares the canonical pgbench
--foreign-keysconstraints (tellers/accounts/history → branches, history → tellers/accounts) on PostgreSQL and MySQL, added post-load in acreate_foreign_keysstep. They were missing — the schema had thebidindexes that exist to back those references but not the references themselves. (YDB/Picodata don't support foreign keys, so the step is a no-op there.) -
Loading wide tables on MySQL no longer fails with
Error 1390(too many placeholders). Bulk-insert batches are now clamped by column count, so wide tables such as TPC-DScatalog_sales(34 columns) load correctly. -
Generated data now loads on YDB. The bulk-upsert path coerces generated cells to the table's declared column types (ISO date strings →
Timestamp, integral quantities →Double), so TPC-H loads on YDB with zero errors; previously these failed withSCHEME_ERROR.
Removed
- The pre-baked TPC-DS query blobs (
tpcds-scale-1.sql…tpcds-scale-100000.sql) are gone — the workload now generates and loads its own data and ships per-dialect query files. Usestroppy run tpcds/tpcds -e SCALE_FACTOR=<n>instead ofstroppy run tpcds tpcds-scale-<n>.
[5.4.0] - 2026-06-22
Added
stroppy probewith no script argument now lists the available preset catalog. (#73)
Fixed
- Clearer error when a probed script has no
optionsexport. (#73) - Fatal log lines no longer dump a goroutine stacktrace. (#73)
[5.3.4] - 2026-06-16
Changed
- Faster data generation and bulk inserts: TPC-H lineitem loading now runs significantly quicker and uses far less memory, with up to ~38% higher throughput on the insert path and large reductions in allocations during generation. (#72)
[5.3.3] - 2026-05-29
Changed
- TPC-H now prepares the database once per run instead of repeating setup work.
Fixed
- Insert throughput is now reported from live progress metrics for more accurate numbers.
[5.3.2] - 2026-05-27
Added
- TPC-H now reports per-query timings for the workload.
Fixed
- Worked around a YDB error that could interrupt TPC-H runs.
[5.3.1] - 2026-05-27
Fixed
- TPC-H totals no longer apply YDB column coalescing, producing correct results.
[5.3.0] - 2026-05-27
Added
- TPC-H can now run against YDB column-store tables.
[5.2.0] - 2026-05-26
Added
- Live insert progress is now reported while data loads. (#71)
- A single TPC-C test can now drive multiple tool instances at once.
- k6 logger settings are now synced with the runner configuration.
Changed
- Faster data generation through performance refactoring.
- YDB data ingestion, table partitioning, and index partitioning settings improved for better load performance.
- YDB now uses lazy transactions and parameter-based IN queries.
- Query arguments now go through dialect conversion, with YDB list parameters still normalized to typed slices.
- TPC-H finalize step is now dynamic.
Fixed
- YDB now retries UNAVAILABLE errors instead of failing.
[5.1.3] - 2026-05-20
Fixed
- TPC-H scale-factor 1 queries now pass on YDB.