Accelerate indexed SQLite complex reads - #171
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This adds a conservative candidate-selection path for complex reads on the TinyMongo SQLite backend.
TinyMongo now reuses declared top-level SQLite expression indexes to narrow positive
$andqueries that have a scalar equality or$inanchor. Safe numeric range and$modpredicates are also applied in SQLite before BSON decoding. The shared Python BSON matcher remains the final authority, so candidate selection cannot change the MongoDB-facing result.No collection-table columns or new storage format are introduced. Existing TinyMongo index metadata and expression indexes are reused, with missing scalar/type companion indexes reconciled lazily.
Why
Complex Mongo-style predicates previously fell back to decoding and testing every document in a SQLite collection, even when the application had already declared a useful index. Large payloads made that substantially slower than the underlying database needed to be.
This change treats SQLite filtering as a conservative pre-query: it reduces the rows transferred and decoded while preserving the established matcher for exact MongoDB semantics.
Implementation details
$andpredicates; it never narrows through$or,$nor, or negative-only expressions.$gt/$gte/$lt/$lteand$modpredicates into SQLite.Performance
Reproducible warmed comparison:
groupindex$and(group $in, i range, i $mod)filterThe TinyMongo path is approximately 11.5x faster than the prior full-scan fallback. MongoDB used acknowledged journaled writes (
w=1, j=true) during setup; writes were not part of the timed read loop.The new benchmark is available at
tests/benchmarks/bench_sqlite_complex_reads.py.Compatibility coverage
Focused tests cover:
$invaluesValidation
3763 passed, 1 skipped, 531 deselectedtinymongo/*ruff check .black --check .mypy --ignore-missing-imports tinymongoThe roadmap records the completed candidate-selective read work and the measured comparison.