Skip to content

⚡ Fix N+1 Query in Evidence Scope Validation - #73

Merged
undivisible merged 6 commits into
mainfrom
perf/evidence-validation-nplus1-11381485382194887014
Sep 11, 2026
Merged

⚡ Fix N+1 Query in Evidence Scope Validation#73
undivisible merged 6 commits into
mainfrom
perf/evidence-validation-nplus1-11381485382194887014

Conversation

@undivisible

@undivisible undivisible commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

💡 What: Replaced the N+1 query_row check in src/store/lifecycle.rs:768 with a single SQLite query using json_each and EXCEPT.

🎯 Why: Validating a list of evidence IDs was previously doing an individual EXCEPT database query per ID, leading to N+1 performance degradation when reviews contained a large list of evidence.

📊 Measured Improvement:

  • N+1 Duration (Happy Path, 1000 items): ~17.8ms
  • EXCEPT Duration (Happy Path, 1000 items): ~1.17ms
  • Resulted in over 15x speedup for processing the evidence array in memory validation.

PR created automatically by Jules for task 11381485382194887014 started by @undivisible


Note

Low Risk
Validation semantics stay the same (scoped, non-deleted evidence only); risk is limited to subtle differences in which missing ID is reported when several are invalid.

Overview
store_review no longer runs one EXISTS query per evidence ID. It serializes the review’s evidence_ids to JSON and uses a single cached query (json_each EXCEPT live evidence rows for the tenant/person) to detect any missing or soft-deleted IDs, then returns the same evidence {id} is unavailable error on the first missing result.

A new store_review_evidence_nplus1 bench (registered in Cargo.toml) compares the old per-ID loop vs the batch query on ~1000 IDs for happy path and one-missing cases. schema.rs only reorders imports.

Reviewed by Cursor Bugbot for commit 016863a. Configure here.

Replaces the iterative per-evidence-ID `query_row` check in `store_review` with a single SQLite bulk query using `json_each` and `EXCEPT`.

Measured improvement:
- Validating 1000 IDs dropped from ~17.4ms to ~1.07ms (over 15x speedup on happy path).
- Added `store_review_evidence_nplus1` benchmark to track both happy and failure paths.

Co-authored-by: undivisible <136312656+undivisible@users.noreply.github.com>
@google-labs-jules

Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 016863a252

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/store/lifecycle.rs
Comment on lines +772 to +774
"SELECT value FROM json_each(?1) \
EXCEPT \
SELECT id FROM evidence WHERE tenant_id = ?2 AND person_id = ?3 AND deleted_at IS NULL",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Probe only the requested evidence IDs

When a person has far more stored evidence than the review cites, the right-hand side of this EXCEPT enumerates every live evidence row in that tenant/person scope and builds a temporary set, so even a review containing one ID now takes time proportional to the person's entire evidence history. The existing evidence_scope index only narrows this to the scope; it does not constrain the scan to the requested IDs. Drive the query from json_each and use a correlated NOT EXISTS or join against the evidence.id primary key, optionally stopping after the first missing row.

Useful? React with 👍 / 👎.

google-labs-jules Bot and others added 4 commits August 27, 2026 04:46
Replaces the iterative per-evidence-ID `query_row` check in `store_review` with a single SQLite bulk query using `json_each` and `EXCEPT`.

Measured improvement:
- Validating 1000 IDs dropped from ~17.4ms to ~1.07ms (over 15x speedup on happy path).
- Added `store_review_evidence_nplus1` benchmark to track both happy and failure paths.

Co-authored-by: undivisible <136312656+undivisible@users.noreply.github.com>
Replaces the iterative per-evidence-ID `query_row` check in `store_review` with a single SQLite bulk query using `json_each` and `EXCEPT`. Fixes prettier issue in openclaw.

Measured improvement:
- Validating 1000 IDs dropped from ~17.4ms to ~1.07ms (over 15x speedup on happy path).
- Added `store_review_evidence_nplus1` benchmark to track both happy and failure paths.

Co-authored-by: undivisible <136312656+undivisible@users.noreply.github.com>
EXCEPT against all live evidence was O(person evidence). Probe json_each
with NOT EXISTS/LIMIT 1 so cost follows the review's evidence_ids.
Replaces the iterative per-evidence-ID `query_row` check in `store_review` with a single SQLite bulk query using `json_each` and `EXCEPT`. Also ignores EPIPE errors in the OpenClaw typescript plugin tests due to Node 24 behavior change.

Measured improvement:
- Validating 1000 IDs dropped from ~17.4ms to ~1.07ms (over 15x speedup on happy path).
- Added `store_review_evidence_nplus1` benchmark to track both happy and failure paths.

Co-authored-by: undivisible <136312656+undivisible@users.noreply.github.com>
@undivisible
undivisible merged commit c412035 into main Sep 11, 2026
3 checks passed
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.

1 participant