Indexing Guide

NebulaDB supports indexing to improve query performance. This guide explains how to use indexes effectively.

Understanding Indexes

Indexes in NebulaDB are data structures that improve the speed of data retrieval operations. They work by creating a reference to the data based on specific fields, allowing the database to find documents without scanning the entire collection.

Index Types

Creating Indexes

When Creating a Collection

import { createDb, IndexType } from '@nebula/core';
import { MemoryAdapter } from '@nebula/adapter-memory';

const db = createDb({ adapter: new MemoryAdapter() });

const users = db.collection('users', {
  indexes: [
    { name: 'email_idx', fields: ['email'], type: IndexType.UNIQUE },
    { name: 'name_age_idx', fields: ['name', 'age'], type: IndexType.COMPOUND }
  ]
});

After Collection Creation

import { IndexType } from '@nebula/core';

users.createIndex({ name: 'age_idx', fields: ['age'], type: IndexType.SINGLE });
users.createIndex({ name: 'username_idx', fields: ['username'], type: IndexType.UNIQUE });
users.createIndex({ name: 'location_idx', fields: ['country', 'city'], type: IndexType.COMPOUND });

Using Indexes

NebulaDB automatically uses indexes when processing queries. For an index to be used, the query must include the indexed fields with equality conditions:

// Will use the 'email_idx' index
const user = await users.findOne({ email: 'alice@example.com' });

// Will use the 'name_age_idx' compound index
const results = await users.find({ name: 'Alice', age: 30 });

// Will NOT use the 'name_age_idx' index (range query on age)
const results = await users.find({ name: 'Alice', age: { $gt: 25 } });

Managing Indexes

Listing Indexes

const indexes = users.getIndexes();
console.log(indexes);
// [{ name: 'email_idx', fields: ['email'], type: 'unique' }, ...]

Dropping Indexes

users.dropIndex('age_idx');

Index Performance Considerations

When to Use Indexes

When to Avoid Indexes

Index Limitations

Best Practices

  1. Index Selectively: Only create indexes that will be used frequently
  2. Use Compound Indexes Wisely: Order fields from most selective to least selective
  3. Monitor Performance: Test queries with and without indexes to ensure they're helping
  4. Avoid Over-Indexing: Too many indexes can degrade write performance
  5. Consider Collection Size: For very small collections, indexes might not be necessary

Example: Optimizing a Query

const products = db.collection('products');

for (let i = 0; i < 10000; i++) {
  await products.insert({
    name: `Product ${i}`,
    category: ['A', 'B', 'C'][i % 3],
    price: Math.floor(Math.random() * 1000),
    inStock: Math.random() > 0.5
  });
}

console.time('Without index');
const resultsWithoutIndex = await products.find({ category: 'B', inStock: true });
console.timeEnd('Without index');

products.createIndex({
  name: 'category_stock_idx',
  fields: ['category', 'inStock'],
  type: IndexType.COMPOUND
});

console.time('With index');
const resultsWithIndex = await products.find({ category: 'B', inStock: true });
console.timeEnd('With index');