--- name: query-plan-snapshot-cli description: Use QueryPlanSnapshotCli to capture and compare RDF4J query plans, then assess likely performance improvements/regressions from execution verification and semantic plan diffs. Trigger when users ask about optimizer impact, query-plan drift, join algorithm changes, or query performance regressions in testsuites/benchmark. --- # query-plan-snapshot-cli Use this skill to run reproducible query-plan captures, triage historical theme-query benchmark results, and classify likely regression/improvement signals. ## Fast workflow 1. Capture raw benchmark output into a normalized result file when needed. 2. Analyze the newest dated run against historical results. 3. Drill into the fastest known runs for a specific theme/query. 4. If needed, capture baseline/candidate plan snapshots and diff them semantically. ## History triage Result files live in: - `core/sail/lmdb/src/test/java/org/eclipse/rdf4j/sail/lmdb/benchmark/theme-query-benchmark-results` Normalize raw JMH output into a new result file: - `pbpaste | scripts/theme-query-benchmark-results.sh capture` - `scripts/theme-query-benchmark-results.sh capture raw-jmh.txt` Analyze only the queries that are more than 20% slower than history: - `core/sail/lmdb/src/test/java/org/eclipse/rdf4j/sail/lmdb/benchmark/theme-query-benchmark-results/analyze-theme-query-history.sh` Sort regressions from biggest to smallest: - `core/sail/lmdb/src/test/java/org/eclipse/rdf4j/sail/lmdb/benchmark/theme-query-benchmark-results/analyze-theme-query-history.sh --sort-regressions` Only print the top N regressions: - `core/sail/lmdb/src/test/java/org/eclipse/rdf4j/sail/lmdb/benchmark/theme-query-benchmark-results/analyze-theme-query-history.sh --top 10` Analyze every latest query, including current-run wins over previous best: - `core/sail/lmdb/src/test/java/org/eclipse/rdf4j/sail/lmdb/benchmark/theme-query-benchmark-results/analyze-theme-query-history.sh --all` Drill into the three fastest known runs for one theme/query and print optimized plan/query when present: - `core/sail/lmdb/src/test/java/org/eclipse/rdf4j/sail/lmdb/benchmark/theme-query-benchmark-results/analyze-theme-query-history.sh --theme PHARMA --query-index 10` Interpretation: - Default mode: newest dated file only for the “latest” baseline; compares against all other `results-*.md`, including `results-develop.md` and `results-main-branch.md`, but prints only queries where latest is more than 20% slower than historical best. - `--sort-regressions`: flat regression list, biggest slowdown first. - `--top N`: top N regressions only; implies regression sorting. - `--all`: prints every latest query; if latest is a new best it prints how much faster it is than the previous best. - Query detail mode: top three runs sorted by score ascending; ties prefer richer files with plan/query content. - `plan no | query yes`: optimized query rendered, no physical plan block in that result file. - `plan no | query no`: summary-only run or no per-query capture in that file. Use this path when the goal is optimizer-loop work: find the fastest known plan/query for a theme/query, then compare new runs back to that history before touching production logic. ## Fast regression test loop (persistent LMDB theme stores) Theme regression/snapshot tests in `core/sail/lmdb` now support reusing a prepared LMDB store across runs. - Enable persistent reuse: - `-Drdf4j.lmdb.themeRegression.persistentStore.enabled=true` - Optional custom root directory: - `-Drdf4j.lmdb.themeRegression.persistentStore.root=persistent-lmdb-theme-store` - Default root directory: - `persistent-lmdb-theme-store` Behavior: - If the store has expected `triples/data.mdb` and `values/data.mdb` sizes (from `expected-db-file-sizes.properties`), tests reuse it and skip rebuild/ingest. - If sizes mismatch or the marker file is missing/invalid, tests rebuild the store, then refresh the expected-size file. Example focused run: - `mvn -o -Dmaven.repo.local=.m2_repo -pl core/sail/lmdb -Dtest=LmdbThemeQueryRegressionTest#socialMediaFiveCycleInterleavesValuesWithFollowsEdges -Drdf4j.lmdb.themeRegression.persistentStore.enabled=true test` ## Snapshot diff workflow Use this when you need semantic plan diffs between two controlled captures of the same query. 1. Capture baseline run (main/reference commit). 2. Capture candidate run (changed commit) with same query selector + `--query-id`. 3. Produce semantic diff (`--compare-existing`). 4. Interpret runtime + diff together. ## Commands Use wrapper (enforces pre-install and optional logging): - Baseline: - `./.codex/skills/query-plan-snapshot-cli/scripts/run_query_plan_snapshot.sh --log /tmp/qps-baseline.log -- --store memory --theme MEDICAL_RECORDS --query-index 0 --query-id med-q0` - Candidate: - `./.codex/skills/query-plan-snapshot-cli/scripts/run_query_plan_snapshot.sh --log /tmp/qps-candidate.log -- --store memory --theme MEDICAL_RECORDS --query-index 0 --query-id med-q0 --compare-latest --diff-mode structure+estimates` - Compare existing snapshots explicitly: - `mvn -o -Dmaven.repo.local=.m2_repo -pl testsuites/benchmark -DskipTests exec:java@query-plan-snapshot -Dexec.args="--compare-existing --query-id med-q0 --compare-indices 1,0 --no-interactive --diff-mode structure+estimates" | tee /tmp/qps-compare.log` - Summarize improvement/regression signal: - `python3 ./.codex/skills/query-plan-snapshot-cli/scripts/interpret_query_plan_regression.py --baseline-log /tmp/qps-baseline.log --candidate-log /tmp/qps-candidate.log --comparison-log /tmp/qps-compare.log` ## Interpretation rule-of-thumb - `averageMillis` down with stable `resultCount`: improvement signal. - `averageMillis` up with stable `resultCount`: regression signal. - `actualResultSizes=diff`: semantic/data-shape risk; perf conclusion low confidence. - `joinAlgorithms=diff` or `structure=diff`: optimizer behavior changed; correlate with runtime delta. - `estimates=diff` only: model/statistics shift; validate with repeated runs. For more detailed reading patterns and triage prompts, use `references/workflow.md`.