Skip to content

perf(sqlite): write search_index rows eight per INSERT (+9%) - #951

Open
angela-helios wants to merge 2 commits into
mainfrom
perf/sqlite-multirow-index
Open

perf(sqlite): write search_index rows eight per INSERT (+9%)#951
angela-helios wants to merge 2 commits into
mainfrom
perf/sqlite-multirow-index

Conversation

@angela-helios

Copy link
Copy Markdown
Contributor

Third item in the SQLite bulk-ingest series (#949 FTS scan, #950 write-path defaults), and the multi-row INSERT lever from #945/#947.

A resource writes ~10–30 search_index rows, each via a single-row prepared INSERT stepped once per row. The B-tree maintenance is the irreducible cost, but entering and leaving the statement per row is not: rows are now written eight per INSERT (8 × 24 positional parameters, single-row remainder), amortizing the per-statement overhead. Same rows, same order, same values — the row-count audit per resource is identical.

Measured

Real 31 GB manifest, identical 7-minute windows, single worker, on top of #949 + #950:

single-row 8-per-INSERT
Throughput 382/s 417/s (+9%)
index-row INSERT cost 1.11 ms/entry 0.85 ms

Also measured and rejected while here: file fan-out ×2 on the optimized write path — 388/s vs 417/s, no lock errors. With extraction and fetch already cheap, a second in-flight file only adds write-lock handoffs; SQLite's default file concurrency of 1 stands (consistent with #946's clamp).

Running total

Stacked local measurement (#944 + #949 + #950 + this): today's main starts at ~110/s and decays; the combined branches hold 417/s stable — a projected ~38 minutes for the full 954,288-entry import, single worker, zero configuration. The 51-minute full-run verification before the last two increments is on #947.

Full sqlite persistence suite green (344).

A resource writes ~10-30 search_index rows, each via a single-row
prepared INSERT stepped once per row. The B-tree maintenance is the
irreducible cost, but entering and leaving the statement per row is
not: batching eight rows per INSERT (with a single-row remainder)
amortizes it.

Measured on the real 31 GB bulk-submit manifest, identical 7-minute
windows, on top of the FTS-scan fix and the write-path pragma defaults:
382/s -> 417/s (+9%), index-row INSERT cost 1.11 -> 0.85 ms per entry,
identical index-row counts per resource.

File fan-out at 2 was also measured on the optimized write path and
came out neutral-to-negative (388/s vs 417/s, no lock errors): with
extraction and fetch already cheap, a second in-flight file only adds
write-lock handoffs. SQLite's default file concurrency of 1 stands.
smunini
smunini previously approved these changes Sep 5, 2026
insert_sql_rows8 was inserted between to_sql_params' doc comment and its
signature, so the new function absorbed those docs and to_sql_params was
left undocumented, failing the workspace `-D missing-docs` lint. Move the
new function above the block and give each its own docs.

Claude-Session: https://claude.ai/code/session_016kNZJTXf86QoMqcdWqKCbR
@codecov

codecov Bot commented Sep 5, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants