Skip to content

Query Optimization ​

Zorix includes an intelligent Query Planner that analyzes your queries and selects the most efficient execution path based on your schema's indexes.

How the Planner Works ​

When you call find(), update(), or delete(), Zorix performs the following steps:

  1. Normalization: Your where clause is converted into a standard set of conditions.
  2. Scoring: Each available index is scored based on its selectivity and the operators being used.
  3. Range Building: The best index is used to create a native IDBKeyRange.
  4. Execution: The query is executed using a native cursor or an optimized range lookup.
  5. Post-Filtering: Any conditions that couldn't be satisfied by the index are filtered in memory.

Operator Selectivity ​

Different operators have different performance characteristics. Zorix scores them accordingly:

OperatorScorePerformance
eq100Maximum (Direct Lookup)
between70High (Bounded Range)
gt, gte, lt, lte60High (One-sided Range)
startsWith50Medium (Prefix Match)
includes40Medium (Multi-entry Scan)
neq10Low (Full Scan Required)

Index Selection Strategy ​

Primary Key ​

Looking up by the Primary Key using .get() is always O(1) and is the fastest possible operation.

Single-Field Indexes ​

For most queries, Zorix will pick the index on the field with the most "selective" operator (e.g., eq is preferred over gt).

Compound Indexes ​

If you have a compound index like ['status', 'createdAt'], Zorix will use it effectively if you filter by both fields.

typescript
// Uses compound index optimized
await Orders.find({
  where: {
    status: 'shipped',
    createdAt: { gte: lastWeek }
  }
});

The "Post-Filter" Phase ​

If your query filters by multiple fields but you only have an index for one of them, Zorix will:

  1. Use the index to fetch a subset of records.
  2. Manually filter the remaining conditions in JavaScript.

🚀 Performance Tip

To avoid the post-filter phase for frequently used query combinations, define a Compound Index in your schema.

Analyzing Plans ​

In development, you can inspect the execution plan (internal feature) to see if your queries are performing a Full Scan (no index used). A full scan is O(n) and should be avoided for large object stores.

Next, explore Advanced Patterns.

Released under the MIT License.