Skip to content

perf(memory): add expires_at to semantic cache index composite (#2030)#2042

Merged
bug-ops merged 2 commits intomainfrom
2030-cache-index-expires-at
Mar 20, 2026
Merged

perf(memory): add expires_at to semantic cache index composite (#2030)#2042
bug-ops merged 2 commits intomainfrom
2030-cache-index-expires-at

Conversation

@bug-ops
Copy link
Copy Markdown
Owner

@bug-ops bug-ops commented Mar 20, 2026

Summary

Fixes issue #2030: The partial index idx_response_cache_semantic on the semantic response cache table was missing the expires_at column. This caused get_semantic() queries to post-filter expired rows from the heap after matching by embedding, rather than excluding them during index traversal.

Changes

  • Migration 038: Drops and recreates idx_response_cache_semantic with expires_at as the second column, following the canonical equality-range-sort B-tree pattern: (embedding_model, expires_at, embedding_ts DESC) WHERE embedding IS NOT NULL
  • Test: Added test_semantic_query_uses_composite_index to validate EXPLAIN QUERY PLAN uses the new index
  • CHANGELOG: Added performance entry documenting the optimization

Design & Validation

  • ✓ Architect design approved
  • ✓ Critic adversarial review passed (3 action items all resolved)
  • ✓ Developer implementation complete (all checks: fmt, clippy 0 warnings, 6015 tests)
  • ✓ Security audit: PASS (idempotent DDL, parameterized queries, no risks)
  • ✓ Impl-critic: APPROVE (no blocking issues)
  • ✓ Perf analysis: optimal column ordering, negligible index size increase
  • ✓ Test coverage: PASS (6015 tests, +1 new test)
  • ✓ Code review: APPROVED

Technical Details

  • Index definition change only, no application code changes
  • Migration is idempotent (safe for both fresh and post-037 databases)
  • Performance benefit: queries with high ratio of expired entries (20-80%) avoid post-filter heap fetches
  • Test validates both migration sequence and query plan optimizer behavior

No functional changes, pure performance optimization.

The partial index idx_response_cache_semantic previously covered
(embedding_model, embedding_ts DESC) but not expires_at. This caused
get_semantic() to post-filter expired rows from the heap after index
scan, rather than excluding them within the index traversal.

Migration 038 recreates the index with expires_at as the second column,
following the canonical equality-range-sort B-tree pattern. Query plan
test validates the optimizer chooses the new index for the exact
get_semantic() predicates.

Fixes #2030. No application code changes, index-only optimization.
@github-actions github-actions bot added performance Performance improvements documentation Improvements or additions to documentation memory zeph-memory crate (SQLite) rust Rust code changes size/S Small PR (11-50 lines) and removed performance Performance improvements labels Mar 20, 2026
@bug-ops bug-ops linked an issue Mar 20, 2026 that may be closed by this pull request
@github-actions github-actions bot added the performance Performance improvements label Mar 20, 2026
@bug-ops bug-ops enabled auto-merge (squash) March 20, 2026 13:52
@bug-ops bug-ops merged commit b1cfd84 into main Mar 20, 2026
25 checks passed
@bug-ops bug-ops deleted the 2030-cache-index-expires-at branch March 20, 2026 13:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation memory zeph-memory crate (SQLite) performance Performance improvements rust Rust code changes size/S Small PR (11-50 lines)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

perf: semantic cache index missing expires_at filter

1 participant