Summary
Composite indexes are fully supported at the storage level (#[index(group = "name")]), but the query planner does not leverage them. The filter analyzer explicitly skips multi-column indexes, and several related query optimizations are missing.
Current State
- B+ tree indexes work for single-column
Eq, Range, and In lookups
- Composite indexes are built, stored in
IndexLedger, and maintained on insert/update/delete
- The filter analyzer (
filter_analyzer.rs) filters to columns.len() == 1, so composite indexes are never used at query time
- AND with predicates on different indexed columns uses only the first index + post-filter
Missing Capabilities
1. Composite index query acceleration
The filter analyzer should recognize when a query's WHERE clause matches a composite index prefix and generate an appropriate IndexPlan. For example, given #[index(group = "category_brand")] on columns (category, brand):
WHERE category = 'X' AND brand = 'Y' → exact composite lookup
WHERE category = 'X' → prefix scan on the composite index
2. OR clause support
Filter::Or(...) currently returns None, forcing a full table scan. Possible strategies:
- Index union: run each branch through the analyzer independently, merge results
- Convert
OR on the same column to IN
3. Multi-index intersection
When an AND has predicates on different indexed columns (e.g., Eq("sku", x) AND Eq("category", y)), the planner could intersect results from both indexes instead of using only one + post-filter.
4. NULL predicate indexing
IsNull / NotNull filters are not handled by the analyzer and always fall through to remaining filter.
5. Index-only scans
Currently, full records are always read after an index lookup. When the query only needs indexed columns, the record fetch could be skipped entirely.
Relevant Files
crates/wasm-dbms/wasm-dbms/src/database/filter_analyzer.rs — filter → index plan conversion
crates/wasm-dbms/wasm-dbms/src/database/index_reader.rs — index query execution
crates/wasm-dbms/wasm-dbms/src/database.rs — try_index_select() integration
crates/wasm-dbms/wasm-dbms-memory/src/table_registry/index_ledger.rs — index storage
Summary
Composite indexes are fully supported at the storage level (
#[index(group = "name")]), but the query planner does not leverage them. The filter analyzer explicitly skips multi-column indexes, and several related query optimizations are missing.Current State
Eq,Range, andInlookupsIndexLedger, and maintained on insert/update/deletefilter_analyzer.rs) filters tocolumns.len() == 1, so composite indexes are never used at query timeMissing Capabilities
1. Composite index query acceleration
The filter analyzer should recognize when a query's WHERE clause matches a composite index prefix and generate an appropriate
IndexPlan. For example, given#[index(group = "category_brand")]on columns(category, brand):WHERE category = 'X' AND brand = 'Y'→ exact composite lookupWHERE category = 'X'→ prefix scan on the composite index2. OR clause support
Filter::Or(...)currently returnsNone, forcing a full table scan. Possible strategies:ORon the same column toIN3. Multi-index intersection
When an AND has predicates on different indexed columns (e.g.,
Eq("sku", x) AND Eq("category", y)), the planner could intersect results from both indexes instead of using only one + post-filter.4. NULL predicate indexing
IsNull/NotNullfilters are not handled by the analyzer and always fall through to remaining filter.5. Index-only scans
Currently, full records are always read after an index lookup. When the query only needs indexed columns, the record fetch could be skipped entirely.
Relevant Files
crates/wasm-dbms/wasm-dbms/src/database/filter_analyzer.rs— filter → index plan conversioncrates/wasm-dbms/wasm-dbms/src/database/index_reader.rs— index query executioncrates/wasm-dbms/wasm-dbms/src/database.rs—try_index_select()integrationcrates/wasm-dbms/wasm-dbms-memory/src/table_registry/index_ledger.rs— index storage