perf(eventcore-sqlite): batch INSERT in append_events (#362) #404

Merged
jwilger merged 1 commit from perf/362-sqlite-batch-insert into main 2026-06-13 07:11:28 -07:00
Owner

Summary

Replaces the per-event INSERT loop in SqliteEventStore::append_events with a single multi-row INSERT ... VALUES (...),(...) statement, chunked to stay well under SQLite's SQLITE_MAX_VARIABLE_NUMBER bound-parameter limit (100 rows / 500 params per statement). All events in one append_events call already share a single transaction, so batching them into one statement removes per-event statement-preparation overhead.

Behavior

Unchanged. Per-stream versions are still assigned sequentially, and the optimistic-concurrency version checks still run before any write. Verified by the existing backend contract suite plus a new integration test that appends a 250-event batch (crossing the 100-row chunk boundary) and reads it back.

Workflow note

Phases 1-3 are not applicable: this is a behavior-preserving internal optimization with no public API change and acceptance criteria already specified in the issue. Existing contract + integration tests are the regression safety net (Phase 4 TDD).

Closes #362

## Summary Replaces the per-event `INSERT` loop in `SqliteEventStore::append_events` with a single multi-row `INSERT ... VALUES (...),(...)` statement, chunked to stay well under SQLite's `SQLITE_MAX_VARIABLE_NUMBER` bound-parameter limit (100 rows / 500 params per statement). All events in one `append_events` call already share a single transaction, so batching them into one statement removes per-event statement-preparation overhead. ## Behavior Unchanged. Per-stream versions are still assigned sequentially, and the optimistic-concurrency version checks still run before any write. Verified by the existing backend contract suite plus a new integration test that appends a 250-event batch (crossing the 100-row chunk boundary) and reads it back. ## Workflow note Phases 1-3 are not applicable: this is a behavior-preserving internal optimization with no public API change and acceptance criteria already specified in the issue. Existing contract + integration tests are the regression safety net (Phase 4 TDD). Closes #362
perf(eventcore-sqlite): batch INSERT in append_events (#362)
All checks were successful
CI / Detect Changes (pull_request) Successful in 3s
auto_review auto_review: no findings
CI / Format (pull_request) Successful in 15s
CI / Request auto_review semantic review (pull_request) Successful in 2s
CI / Clippy (pull_request) Successful in 1m56s
CI / Security Audit (pull_request) Successful in 24s
CI / Test (pull_request) Successful in 2m52s
CI / Mutation (pull_request) Has been skipped
CI / CI Gate (pull_request) Successful in 2s
d83f7448d9
Replace the per-event INSERT loop in `SqliteEventStore::append_events`
with a single multi-row `INSERT ... VALUES (...),(...)` statement,
chunked to stay well under SQLite's bound-parameter limit
(SQLITE_MAX_VARIABLE_NUMBER). All events in one append_events call
share a single transaction, so writing them in one statement removes
per-event statement-preparation overhead.

Behavior is unchanged: per-stream versions are still assigned
sequentially and the version-conflict checks run before any write.
Adds an integration test that appends a batch larger than one INSERT
chunk (250 events) and reads it back, exercising the chunk boundary.

Workflow note: Phases 1-3 are not applicable — this is a
behavior-preserving internal optimization with no public API change and
acceptance criteria already specified in issue #362. Existing contract
and integration tests are the regression safety net (Phase 4 TDD).

Closes #362
auto-review left a comment

This PR optimizes the append_events function by batching INSERT operations into a single multi-row statement, improving performance without changing behavior. The changes are well-tested and appear safe to merge.

Walkthrough

  • eventcore-sqlite/src/lib.rs:
    • Replaced the per-event INSERT loop with a batched multi-row INSERT statement.
    • Introduced bound_values to collect parameters for the batched INSERT.
    • Added logic to chunk the INSERT statements to respect SQLite's parameter limit.
  • eventcore-sqlite/tests/batch_append_test.rs:
    • Added a new test to verify that a large batch of events is correctly persisted across chunk boundaries.

LLM usage and cost

This PR optimizes the `append_events` function by batching INSERT operations into a single multi-row statement, improving performance without changing behavior. The changes are well-tested and appear safe to merge. ## Walkthrough - **eventcore-sqlite/src/lib.rs**: - Replaced the per-event INSERT loop with a batched multi-row INSERT statement. - Introduced `bound_values` to collect parameters for the batched INSERT. - Added logic to chunk the INSERT statements to respect SQLite's parameter limit. - **eventcore-sqlite/tests/batch_append_test.rs**: - Added a new test to verify that a large batch of events is correctly persisted across chunk boundaries. ## LLM usage and cost - Reasoning (gpt-4o) in=2287 out=288 cost=$0.015755 - Cheap (gpt-4o-mini) in=489 out=56 cost=$0.000107 Estimated total USD: $0.015862 via https://api.openai.com and https://api.openai.com
jwilger deleted branch perf/362-sqlite-batch-insert 2026-06-13 07:11:28 -07:00
Sign in to join this conversation.
No description provided.