Indexes in SyndrDB dramatically improve query performance by creating fast lookup structures for specific fields. SyndrDB supports two types of indexes:
WHERE field == value)WHERE field > value)ð Performance Impact: B-Tree indexes can provide 10.6x performance improvement for range queries!
Hash indexes provide constant-time O(1) lookups for exact match queries. They use a hash table structure optimized for equality comparisons.
Use Cases:
WHERE DocumentID == "abc-123"WHERE user_id == 42WHERE status == "active"WHERE verified == trueArchitecture:
Limitations:
>, <, >=, <=)LIKE)==, !=)B-Tree (Balanced Tree) indexes provide logarithmic O(log n) lookups and support both equality and range queries. They maintain sorted data for efficient range scans.
Use Cases:
WHERE age > 18, WHERE price < 100ORDER BY created_dateWHERE salary >= 50000WHERE score >= 70 AND score <= 100Architecture:
Performance:
Limitations:
CREATE HASH INDEX "<INDEX_NAME>" ON BUNDLE "<BUNDLE_NAME>"
WITH FIELDS (
{"<FIELD_NAME>", <REQUIRED>, <UNIQUE>}
);
Note: Hash indexes currently support single field only.
CREATE B-INDEX "<INDEX_NAME>" ON BUNDLE "<BUNDLE_NAME>"
WITH FIELDS (
{"<FIELD_NAME>", <REQUIRED>, <UNIQUE>}
);
Composite Index Syntax (future support):
CREATE B-INDEX "<INDEX_NAME>" ON BUNDLE "<BUNDLE_NAME>"
WITH FIELDS (
{"<FIELD_NAME_1>", <REQUIRED>, <UNIQUE>},
{"<FIELD_NAME_2>", <REQUIRED>, <UNIQUE>}
);
The CREATE keyword initiates index creation. Indexes are built asynchronously and become available immediately for queries.
Characteristics:
The HASH INDEX keywords specify creation of a hash-based index optimized for equality lookups.
Syntax:
CREATE HASH INDEX "<name>" ...
Characteristics:
The B-INDEX keyword specifies creation of a B-Tree index optimized for range queries and sorting.
Syntax:
CREATE B-INDEX "<name>" ...
Characteristics:
>, <, >=, <=)Note: The keyword is B-INDEX not BTREE INDEX or B-TREE INDEX.
The ON BUNDLE keywords specify which bundle (table) the index applies to.
Syntax:
ON BUNDLE "<BUNDLE_NAME>"
Characteristics:
indexes/ subdirectoryThe WITH FIELDS clause defines which fields to index and their properties.
Syntax:
WITH FIELDS (
{"<FIELD_NAME>", <REQUIRED>, <UNIQUE>}
)
Characteristics:
{}Each field definition follows this exact syntax:
{"<FIELD_NAME>", <REQUIRED>, <UNIQUE>}
Components:
"field_name"Valid examples:
"user_id"
"DocumentID"
"created_date"
"field-with-dashes"
Controls whether the field must exist in all documents.
| Value | Meaning | Use Case |
|---|---|---|
true |
Field must exist in all docs | Primary keys, required fields |
false |
Field can be missing in some docs | Optional fields, nullable columns |
Examples:
{"DocumentID", true, true} -- DocumentID is always present
{"middle_name", false, false} -- middle_name is optional
Controls whether field values must be unique across all documents.
| Value | Meaning | Use Case |
|---|---|---|
true |
Values must be unique | Primary keys, email addresses |
false |
Values can be duplicated | Foreign keys, status fields |
Examples:
{"email", true, true} -- Email must be unique
{"category_id", false, false} -- Multiple docs can have same category
Important: Unique constraints are enforced at insert/update time.
CREATE HASH INDEX "idx_document_id" ON BUNDLE "users"
WITH FIELDS (
{"DocumentID", true, true}
);
Perfect for: WHERE DocumentID == "abc-123"
CREATE HASH INDEX "idx_user_id" ON BUNDLE "orders"
WITH FIELDS (
{"user_id", false, false}
);
Perfect for: WHERE user_id == 42
CREATE HASH INDEX "idx_email" ON BUNDLE "users"
WITH FIELDS (
{"email", true, true}
);
Perfect for: WHERE email == "user@example.com"
CREATE HASH INDEX "idx_status" ON BUNDLE "orders"
WITH FIELDS (
{"status", true, false}
);
Perfect for: WHERE status == "pending"
CREATE HASH INDEX "idx_category" ON BUNDLE "products"
WITH FIELDS (
{"category", false, false}
);
Perfect for: WHERE category == "electronics"
CREATE B-INDEX "idx_age" ON BUNDLE "users"
WITH FIELDS (
{"age", false, false}
);
Perfect for:
WHERE age > 18WHERE age >= 21 AND age <= 65ORDER BY ageCREATE B-INDEX "idx_price" ON BUNDLE "products"
WITH FIELDS (
{"price", true, false}
);
Perfect for:
WHERE price < 100WHERE price >= 50 AND price <= 200ORDER BY price DESCCREATE B-INDEX "idx_created" ON BUNDLE "orders"
WITH FIELDS (
{"created_date", true, false}
);
Perfect for:
WHERE created_date > "2024-01-01"WHERE created_date >= "2024-01-01" AND created_date <= "2024-12-31"ORDER BY created_date DESCCREATE B-INDEX "idx_score" ON BUNDLE "test_results"
WITH FIELDS (
{"score", true, false}
);
Perfect for:
WHERE score >= 70WHERE score > 90ORDER BY score DESC LIMIT 10Composite B-Tree Index (future support):
CREATE B-INDEX "idx_user_date" ON BUNDLE "orders"
WITH FIELDS (
{"user_id", true, false},
{"created_date", true, false}
);
Perfect for:
WHERE user_id == 42 ORDER BY created_dateWHERE user_id == 42 AND created_date > "2024-01-01"Note: Composite indexes are planned but not yet fully implemented.
| Operation | Performance | Use Case |
|---|---|---|
| Exact match | O(1) - Constant time | WHERE id == 123 |
| Multiple matches | O(1) per lookup | WHERE status == "active" |
| Index creation | O(n) - Linear | One-time cost |
| Insert/Update | O(1) - Constant | MemTable write |
Benchmark Results:
| Operation | Performance | Use Case |
|---|---|---|
| Exact match | O(log n) | WHERE id == 123 |
| Range scan | O(log n + k) | WHERE age > 18 |
| Index creation | O(n log n) | One-time cost |
| Insert/Update | O(log n) | Tree rebalancing |
Benchmark Results:
k = number of results returned
| Aspect | Impact |
|---|---|
| Disk space | ~20-30% of data size per index |
| Memory | MemTable (hash) or tree nodes (btree) |
| Insert time | +5-10% per index |
| Update time | +5-10% per index |
| Idle overhead | Minimal when not queried |
Recommendation: Only create indexes on fields you frequently query.
Index frequently queried fields:
-- If you often query by status, create an index
CREATE HASH INDEX "idx_status" ON BUNDLE "orders"
WITH FIELDS ({"status", true, false});
Use hash indexes for exact matches:
-- For WHERE field == value
CREATE HASH INDEX "idx_email" ON BUNDLE "users"
WITH FIELDS ({"email", true, true});
Use B-Tree indexes for ranges:
-- For WHERE field > value
CREATE B-INDEX "idx_age" ON BUNDLE "users"
WITH FIELDS ({"age", false, false});
Index foreign keys:
-- Automatic for relationships, but can create manually
CREATE HASH INDEX "idx_user_fk" ON BUNDLE "orders"
WITH FIELDS ({"user_id", false, false});
Use descriptive index names:
CREATE HASH INDEX "idx_users_email_unique" ... -- â
Clear purpose
CREATE B-INDEX "idx_products_price_range" ... -- â
Indicates usage
Set unique=true for unique constraints:
-- Enforce email uniqueness at database level
CREATE HASH INDEX "idx_email" ON BUNDLE "users"
WITH FIELDS ({"email", true, true});
Don't over-index:
-- â Don't index every field
CREATE HASH INDEX "idx_field1" ...
CREATE HASH INDEX "idx_field2" ...
CREATE HASH INDEX "idx_field3" ...
CREATE HASH INDEX "idx_field4" ...
CREATE HASH INDEX "idx_field5" ...
Don't use hash indexes for ranges:
-- â Wrong index type
CREATE HASH INDEX "idx_age" ON BUNDLE "users"
WITH FIELDS ({"age", false, false});
-- This won't help: WHERE age > 18
Don't use B-Tree for simple equality when hash is faster:
-- â Slower than hash for exact matches
CREATE B-INDEX "idx_id" ON BUNDLE "users"
WITH FIELDS ({"DocumentID", true, true});
-- â
Better
CREATE HASH INDEX "idx_id" ON BUNDLE "users"
WITH FIELDS ({"DocumentID", true, true});
Don't use generic index names:
CREATE HASH INDEX "index1" ... -- â Unclear purpose
CREATE HASH INDEX "idx" ... -- â Too vague
Don't index low-cardinality fields (few distinct values):
-- â Only has 2 values (true/false)
CREATE HASH INDEX "idx_active" ON BUNDLE "users"
WITH FIELDS ({"is_active", true, false});
Don't create duplicate indexes:
-- â Already have idx_email, don't create another
CREATE HASH INDEX "idx_email2" ON BUNDLE "users"
WITH FIELDS ({"email", true, true});
Error: index 'idx_email' already exists in bundle 'users'
Solution: Use a different index name or drop the existing index first.
Error: bundle 'products' not found
Solution: Verify bundle name (case-sensitive) and ensure it exists.
SHOW BUNDLES; -- List all bundles
Error: field 'email' does not exist in bundle 'users'
Solution: Check bundle schema and use correct field name.
SHOW BUNDLE "users"; -- View bundle structure
Error: invalid field definitions syntax
Solution: Ensure proper syntax with curly braces and commas.
-- â Wrong
WITH FIELDS ("email", true, true)
-- â
Correct
WITH FIELDS ({"email", true, true})
Error: invalid CREATE HASH INDEX command syntax
Solution: Include WITH FIELDS clause.
-- â Wrong
CREATE HASH INDEX "idx_email" ON BUNDLE "users";
-- â
Correct
CREATE HASH INDEX "idx_email" ON BUNDLE "users"
WITH FIELDS ({"email", true, true});
Error: invalid field definition in CREATE HASH INDEX command
Solution: Use lowercase true or false (not TRUE/FALSE/1/0).
-- â Wrong
WITH FIELDS ({"email", TRUE, FALSE})
-- â
Correct
WITH FIELDS ({"email", true, false})
Error: unique constraint violation - duplicate value 'user@example.com' for field 'email'
Solution: Remove duplicates before creating unique index, or set unique=false.
CREATE HASH INDEX "<INDEX_NAME>" ON BUNDLE "<BUNDLE_NAME>"
WITH FIELDS (
{"<FIELD_NAME>", <REQUIRED>, <UNIQUE>}
);
Example:
CREATE HASH INDEX "idx_email" ON BUNDLE "users"
WITH FIELDS ({"email", true, true});
CREATE B-INDEX "<INDEX_NAME>" ON BUNDLE "<BUNDLE_NAME>"
WITH FIELDS (
{"<FIELD_NAME>", <REQUIRED>, <UNIQUE>}
);
Example:
CREATE B-INDEX "idx_age" ON BUNDLE "users"
WITH FIELDS ({"age", false, false});
| Query Type | Index Type | Reason |
|---|---|---|
WHERE id == 123 |
Hash | O(1) exact match |
WHERE age > 18 |
B-Tree | Range query support |
WHERE status == "active" |
Hash | Equality check |
WHERE price >= 50 AND price <= 100 |
B-Tree | Range query |
ORDER BY created_date |
B-Tree | Sorted access |
WHERE email == "user@example.com" |
Hash | Unique lookup |
WHERE score > 90 |
B-Tree | Greater than |
| Property | Type | Values | Purpose |
|---|---|---|---|
| Field Name | String | "field_name" |
Which field to index |
| Required | Boolean | true, false |
Must exist in all docs? |
| Unique | Boolean | true, false |
Enforce uniqueness? |
Template:
{"<field_name>", <required>, <unique>}
| Use Case | Index Configuration |
|---|---|
| Primary Key | {"DocumentID", true, true} - Hash |
| Foreign Key | {"user_id", false, false} - Hash |
| Unique Email | {"email", true, true} - Hash |
| Age Range | {"age", false, false} - B-Tree |
| Price Range | {"price", true, false} - B-Tree |
| Optional Field | {"field", false, false} - Either |
Version: SyndrDB 1.0
Last Updated: November 2024
Status: â
Implemented and tested
Create indexes before bulk inserts
Use selective indexes
Monitor index usage
Consider composite indexes (when supported)
Balance read vs write performance
Track these metrics to evaluate index effectiveness:
| Metric | Good | Bad | Action |
|---|---|---|---|
| Index hit rate | > 80% | < 50% | Remove unused indexes |
| Query speedup | > 5x | < 2x | Consider different index type |
| Insert overhead | < 20% | > 50% | Reduce number of indexes |
| Disk usage | < 50% of data | > 100% of data | Optimize or remove |
Happy Indexing! ðŊ