Skip to content

Commit 737e28c

Browse files
committed
feat: add scenario profiles, profile docs, and min_pg_version contract
- Add four bundled profiles: queue_skip_locked (FOR UPDATE SKIP LOCKED queue), jsonb_docs (GIN/jsonb_set document store), partition_aging (daily partitions with aging DDL), bloat_vacuum (non-HOT churn with scheduled VACUUM and bloat reporting) - Ship a README.md with every bundled profile: scenario, jobs, pg_diag watch list, scale and observation guidance - Add docs/profile-authoring-cookbook.md: profile contract reference, generator conventions, and worked recipes - Add optional min_pg_version to the pg_workload/v1 contract; install queries server_version_num and rejects profiles on too-old targets (jsonb_docs requires PostgreSQL 12) - Fix CLI overrides: --pgbench-duration/--pgbench-transactions now take precedence over the profile's transactions/duration - Extend the Docker smoke test with per-profile post-run invariants - Bump version to 0.4.0
1 parent 051d322 commit 737e28c

43 files changed

Lines changed: 1592 additions & 11 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,14 +172,25 @@ Use `--bin-dir /path/to/postgresql/bin` when client binaries are outside
172172
| `many_objects` | Metadata-heavy schemas and partitions | scale-aware SQL object creation |
173173
| `emulate_errors` | Intentional SQL errors | SQL seed rows only |
174174
| `pss_overflow` | `pg_stat_statements` churn | scaled Python generator; extension/preload required |
175+
| `queue_skip_locked` | Producer/consumer task queue with `FOR UPDATE SKIP LOCKED` | synthetic Python generator |
176+
| `jsonb_docs` | JSONB document store with GIN containment and `jsonb_set` updates | synthetic Python generator |
177+
| `partition_aging` | Daily-partitioned time-series with partition pruning and aging DDL | synthetic Python generator |
178+
| `bloat_vacuum` | Dead-tuple churn from non-HOT updates with scheduled `VACUUM` | synthetic Python generator |
175179

176180
No profile requires a dump, CSV file, or network download. The Pagila schema is redistributed
177181
under its upstream license; see `THIRD_PARTY_NOTICES.md`. Its rows are generated locally. The
178182
bundled `imdb` profile is an original, compact movie-domain model and does not contain Join Order
179183
Benchmark SQL or IMDB source data.
180184

185+
Every profile directory contains a `README.md` with the scenario description, its jobs, the
186+
pg_diag sections it is meant to exercise, and scale/observation guidance.
187+
181188
## Profile contract
182189

190+
See [docs/profile-authoring-cookbook.md](docs/profile-authoring-cookbook.md) for a complete
191+
guide to writing custom profiles, including generator conventions and worked recipes for
192+
queue, JSONB, partitioning, and bloat scenarios.
193+
183194
Profiles live at `data/<profile>/profile.yml`. Version 1 is identified by the stable string
184195
`pg_workload/v1`:
185196

@@ -189,6 +200,7 @@ name: my_workload
189200
schema: my_workload
190201
description: Small example workload.
191202
requires_write: false
203+
min_pg_version: 12 # optional major-version floor for the target server
192204

193205
prepare:
194206
steps:
@@ -226,14 +238,18 @@ conditions that JSON Schema alone cannot safely enforce:
226238
- job names are unique and types are `pgbench` or `psql`;
227239
- a pgbench job defines exactly one of `duration` or `transactions`;
228240
- threads do not exceed clients;
241+
- `min_pg_version`, when present, is an integer major version of at least 10;
229242
- SQL files, generators, script globs, and logs stay inside their profile boundary even when
230243
symlinks are present;
231244
- generator steps reference an existing Python file;
232245
- referenced local SQL and pgbench scripts exist before any database operation begins.
233246

234247
`validate` checks the complete contract and all local paths without connecting to PostgreSQL.
235248
`install` executes `prepare.steps` in declared order. A normal data profile therefore creates its
236-
schema, runs its generator, and only then creates indexes and statistics.
249+
schema, runs its generator, and only then creates indexes and statistics. When a profile declares
250+
`min_pg_version`, `install` also queries the target `server_version_num` and refuses to install
251+
on an older server — this fails fast instead of breaking later on a missing feature
252+
(for example, `jsonb_docs` requires PostgreSQL 12 for SQL/JSON path queries).
237253

238254
```bash
239255
pg-workload validate
@@ -281,6 +297,10 @@ pg-workload run --profile simple_stock --pgbench-transactions 100
281297
| `simple_stock_spec_symbols` | the same cardinalities with hostile and Unicode identifiers/values |
282298
| `imdb` | 10,000 companies; 100,000 people; 100,000 titles; 1,300,000 fact rows |
283299
| `pagila` | 600 customers; 1,000 films; 4,500 inventory; 16,000 rentals; 16,500 payments |
300+
| `queue_skip_locked` | 20,000 pending + 5,000 done queue tasks |
301+
| `jsonb_docs` | 50,000 JSONB documents |
302+
| `partition_aging` | 33 daily partitions; 200,000 events skewed toward recent days |
303+
| `bloat_vacuum` | 100,000 accounts, pre-bloated by one non-HOT update round |
284304

285305
For example, `--scale 2` approximately doubles scalable tables. Very small values retain a
286306
profile-specific minimum so foreign-key structure and query selectivity remain meaningful in CI.
@@ -358,6 +378,7 @@ After `init`, the working directory is:
358378
project/
359379
data/<profile>/
360380
profile.yml
381+
README.md # scenario, jobs, pg_diag watch list, scale guidance
361382
generator.py # only when the profile needs table data
362383
sql/
363384
log/ # runtime, ignored

0 commit comments

Comments
 (0)