-
Notifications
You must be signed in to change notification settings - Fork 1
Tutorial SCHEMA DESIGN
Master the art of designing optimal database schemas for ThemisDB. Learn multi-model design patterns, normalization strategies, and real-world examples.
- β Multi-model schema design principles
- β Normalization vs. denormalization trade-offs
- β Index strategy and placement
- β Relationship modeling patterns
- β Real-world schema examples
- β Performance optimization techniques
Prerequisites: CRUD Tutorial, Batch Operations
Time Required: 45 minutes
Difficulty: Intermediate to Advanced
- Design Principles
- Entity-Attribute Model
- Normalization Strategies
- Relationship Patterns
- Index Design
- Real-World Examples
- Migration Patterns
Before designing, answer:
- How will data be queried most often?
- What are the read/write ratios?
- What are the latency requirements?
- What consistency guarantees are needed?
Example:
E-commerce scenario:
- Products: 90% reads, 10% writes β Optimize for reads
- Orders: 50% reads, 50% writes β Balance both
- Analytics: 100% reads β Aggressive denormalization OK
ThemisDB supports multiple models. Choose based on use case:
| Model | Best For | Example |
|---|---|---|
| Key-Value | Simple lookups | User sessions, cache |
| Document | Hierarchical data | Product catalogs, CMS |
| Graph | Relationships | Social networks, recommendations |
| Vector | Similarity search | Image search, semantic search |
β
Good approach:
1. Start with simple schema
2. Monitor performance
3. Add indexes where needed
4. Denormalize hot paths
5. Split large entities
β Bad approach:
1. Over-engineer from day 1
2. Premature optimization
3. Complex schema before understanding access patterns
In ThemisDB, an entity is a unique identifier with attributes:
Format: namespace:key
Example: users:alice, products:12345, orders:ord-2024-001
Best Practices:
- Use meaningful namespaces
- Keep keys human-readable when possible
- Use consistent naming conventions
Two approaches:
1. Blob Storage (Simple)
{
"entity_id": "users:alice",
"blob": "{\"name\":\"Alice\",\"email\":\"alice@example.com\",\"age\":30}"
}- Pros: Simple, flexible
- Cons: Can't query individual fields efficiently
2. Structured Attributes (Advanced)
{
"entity_id": "users:alice",
"attributes": {
"name": "Alice",
"email": "alice@example.com",
"age": 30,
"created_at": "2025-01-24T10:00:00Z"
}
}- Pros: Query individual fields, selective indexing
- Cons: Slightly more complex
π‘ Pro Tip: Start with blobs, migrate to structured attributes when you need to query specific fields.
Example: E-commerce
// users:alice
{
"entity_id": "users:alice",
"attributes": {
"name": "Alice Johnson",
"email": "alice@example.com"
}
}
// orders:order-001
{
"entity_id": "orders:order-001",
"attributes": {
"user_id": "users:alice",
"total": 129.99,
"status": "shipped"
}
}
// order_items:item-001
{
"entity_id": "order_items:item-001",
"attributes": {
"order_id": "orders:order-001",
"product_id": "products:laptop-001",
"quantity": 1,
"price": 129.99
}
}Pros:
- β No data duplication
- β Easy to update
- β Consistent data
Cons:
- β Multiple queries to fetch related data
- β Slower read performance
// orders:order-001 (with embedded data)
{
"entity_id": "orders:order-001",
"attributes": {
"user": {
"id": "users:alice",
"name": "Alice Johnson",
"email": "alice@example.com"
},
"items": [
{
"product_id": "products:laptop-001",
"product_name": "ThinkPad X1",
"quantity": 1,
"price": 129.99
}
],
"total": 129.99,
"status": "shipped",
"created_at": "2025-01-24T10:00:00Z"
}
}Pros:
- β Single query to fetch everything
- β Fast reads
- β Perfect for display
Cons:
- β Data duplication
- β Harder to update (must update multiple places)
- β Possible inconsistency
Normalize by default, denormalize read-heavy paths:
// orders:order-001 (hybrid)
{
"entity_id": "orders:order-001",
"attributes": {
"user_id": "users:alice",
"user_name": "Alice Johnson", // Denormalized for display
"item_ids": ["order_items:item-001"],
"item_summary": "1 item(s)", // Denormalized for quick display
"total": 129.99,
"status": "shipped"
}
}When to denormalize:
- Read-heavy data (90%+ reads)
- Display-only fields (names, summaries)
- Performance-critical paths
When to normalize:
- Frequently updated data
- Source of truth
- Data integrity is critical
Example: User β Profile
// users:alice
{
"entity_id": "users:alice",
"attributes": {
"name": "Alice",
"email": "alice@example.com",
"profile_id": "profiles:alice"
}
}
// profiles:alice
{
"entity_id": "profiles:alice",
"attributes": {
"bio": "Software Engineer",
"avatar": "https://...",
"website": "https://alice.dev"
}
}Alternative (Embedded):
// users:alice
{
"entity_id": "users:alice",
"attributes": {
"name": "Alice",
"email": "alice@example.com",
"profile": {
"bio": "Software Engineer",
"avatar": "https://...",
"website": "https://alice.dev"
}
}
}Example: User β Orders
Approach 1: Reference in child (Normalized)
// users:alice
{
"entity_id": "users:alice",
"attributes": {"name": "Alice"}
}
// orders:order-001
{
"entity_id": "orders:order-001",
"attributes": {
"user_id": "users:alice",
"total": 99.99
}
}
// Query: Find all orders for Alice
POST /query
{
"table": "orders",
"predicates": [{"column": "user_id", "value": "users:alice"}]
}Approach 2: Array of references in parent (Denormalized)
// users:alice
{
"entity_id": "users:alice",
"attributes": {
"name": "Alice",
"order_ids": ["orders:order-001", "orders:order-002"]
}
}Example: Students β Courses
Approach: Junction entity
// students:alice
{
"entity_id": "students:alice",
"attributes": {"name": "Alice"}
}
// courses:cs101
{
"entity_id": "courses:cs101",
"attributes": {"name": "Computer Science 101"}
}
// enrollments:alice-cs101
{
"entity_id": "enrollments:alice-cs101",
"attributes": {
"student_id": "students:alice",
"course_id": "courses:cs101",
"enrolled_at": "2025-01-01",
"grade": "A"
}
}Query: Find all courses for Alice
curl -X POST http://localhost:8080/query \
-d '{
"table": "enrollments",
"predicates": [{"column": "student_id", "value": "students:alice"}],
"return": "entities"
}'For complex relationships, use graph model:
# Create edge between entities
curl -X POST http://localhost:8080/graph/edge \
-d '{
"from": "users:alice",
"to": "users:bob",
"type": "follows",
"properties": {"since": "2025-01-01"}
}'
# Query: Find all users Alice follows
curl -X POST http://localhost:8080/graph/traverse \
-d '{
"start": "users:alice",
"direction": "outbound",
"edge_type": "follows",
"depth": 1
}'Golden Rules:
- Index columns used in WHERE clauses
- Index columns used in ORDER BY
- Index foreign key columns
- Don't over-index (slows writes)
1. B-Tree Index (General Purpose)
# Create B-Tree index on age for range queries
curl -X POST http://localhost:8080/index/create \
-d '{
"table": "users",
"column": "age",
"type": "btree"
}'
# Supports: =, !=, <, >, <=, >=, BETWEEN2. Hash Index (Exact Match)
# Create Hash index on email for fast lookups
curl -X POST http://localhost:8080/index/create \
-d '{
"table": "users",
"column": "email",
"type": "hash"
}'
# Supports: = only (but VERY fast)3. Composite Index
# Create composite index for multi-column queries
curl -X POST http://localhost:8080/index/create \
-d '{
"table": "orders",
"columns": ["user_id", "status", "created_at"],
"type": "btree"
}'
# Optimizes: WHERE user_id=? AND status=? ORDER BY created_at4. Vector Index (Similarity Search)
# Create vector index for embeddings
curl -X POST http://localhost:8080/index/create \
-d '{
"table": "documents",
"column": "embedding",
"type": "vector",
"dimension": 768,
"metric": "cosine"
}'Example: E-commerce queries
// Common queries:
1. Find product by ID β Hash index on product_id
2. Search products by category β B-Tree index on category
3. Filter by price range β B-Tree index on price
4. Sort by popularity β B-Tree index on sales_count
5. Similar products β Vector index on embedding
Indexes to create:
β
products.product_id (hash)
β
products.category (btree)
β
products.price (btree)
β
products.(category, price) (composite)
β
products.embedding (vector)
β Bad: Too many indexes
users.id (hash)
users.email (hash)
users.name (btree)
users.age (btree)
users.city (btree)
users.country (btree)
users.created_at (btree)
users.updated_at (btree)
// 8 indexes = slow writes!
β Good: Strategic indexes
users.id (hash) β Primary key lookup
users.email (hash) β Login authentication
users.(city, age) (composite) β Common filter
// 3 indexes = fast reads + fast writes
Entities:
// users:alice
{
"entity_id": "users:alice",
"attributes": {
"username": "alice",
"display_name": "Alice Johnson",
"bio": "Software Engineer",
"follower_count": 1520, // Denormalized for performance
"following_count": 342
}
}
// posts:post-12345
{
"entity_id": "posts:post-12345",
"attributes": {
"author_id": "users:alice",
"author_name": "Alice Johnson", // Denormalized
"content": "Just deployed ThemisDB!",
"like_count": 45, // Denormalized
"comment_count": 12, // Denormalized
"created_at": "2025-01-24T10:00:00Z"
}
}
// follows:alice-bob (graph edge)
{
"entity_id": "follows:alice-bob",
"attributes": {
"from_user": "users:alice",
"to_user": "users:bob",
"created_at": "2025-01-20T08:00:00Z"
}
}Indexes:
# User lookups
POST /index/create {"table": "users", "column": "username", "type": "hash"}
# Timeline queries (posts by followed users)
POST /index/create {"table": "posts", "columns": ["author_id", "created_at"], "type": "btree"}
# Graph traversal (followers/following)
POST /index/create {"table": "follows", "column": "from_user", "type": "btree"}
POST /index/create {"table": "follows", "column": "to_user", "type": "btree"}Why this design?
- Denormalized counts for fast display
- Graph edges for relationship queries
- Composite index for timeline optimization
// products:laptop-001
{
"entity_id": "products:laptop-001",
"attributes": {
"sku": "LAPTOP-001",
"name": "ThinkPad X1 Carbon",
"description": "High-performance laptop",
"price": 1299.99,
"original_price": 1499.99,
"discount_percent": 13,
"category": "Electronics > Laptops",
"tags": ["business", "ultralight", "premium"],
"stock": 15,
"rating_avg": 4.7, // Denormalized
"review_count": 234, // Denormalized
"embedding": [0.1, 0.2, ...] // For similar products
}
}
// orders:order-2024-001
{
"entity_id": "orders:order-2024-001",
"attributes": {
"user_id": "users:alice",
"user_name": "Alice Johnson", // Denormalized
"status": "shipped",
"total": 1299.99,
"shipping_address": {...},
"items": [ // Embedded for performance
{
"product_id": "products:laptop-001",
"product_name": "ThinkPad X1 Carbon",
"quantity": 1,
"price": 1299.99
}
],
"created_at": "2025-01-24T10:00:00Z"
}
}
// reviews:review-001
{
"entity_id": "reviews:review-001",
"attributes": {
"product_id": "products:laptop-001",
"user_id": "users:alice",
"user_name": "Alice J.", // Partial denormalization
"rating": 5,
"title": "Excellent laptop!",
"content": "Best purchase ever...",
"verified_purchase": true,
"created_at": "2025-01-25T14:30:00Z"
}
}Indexes:
# Product search and filtering
POST /index/create {"table": "products", "column": "category", "type": "btree"}
POST /index/create {"table": "products", "columns": ["category", "price"], "type": "btree"}
POST /index/create {"table": "products", "column": "embedding", "type": "vector", "dimension": 768}
# Order management
POST /index/create {"table": "orders", "columns": ["user_id", "status"], "type": "btree"}
POST /index/create {"table": "orders", "columns": ["status", "created_at"], "type": "btree"}
# Reviews
POST /index/create {"table": "reviews", "column": "product_id", "type": "btree"}
POST /index/create {"table": "reviews", "columns": ["product_id", "created_at"], "type": "btree"}// sensors:temp-sensor-001
{
"entity_id": "sensors:temp-sensor-001",
"attributes": {
"name": "Temperature Sensor 1",
"location": "Building A, Floor 3",
"type": "temperature",
"unit": "celsius",
"last_reading": 22.5, // Denormalized for quick check
"last_update": "2025-01-24T15:30:00Z",
"status": "online"
}
}
// readings:temp-sensor-001-2025-01-24-15-30-00
{
"entity_id": "readings:temp-sensor-001-2025-01-24-15-30-00",
"attributes": {
"sensor_id": "sensors:temp-sensor-001",
"sensor_type": "temperature", // Denormalized for queries
"value": 22.5,
"timestamp": "2025-01-24T15:30:00Z",
"quality": "good"
}
}Time-Series Optimization:
# Partition readings by time (hourly buckets)
# readings:temp-sensor-001-2025-01-24-15
# Contains all readings for that hour
# Index for time-range queries
POST /index/create {"table": "readings", "columns": ["sensor_id", "timestamp"], "type": "btree"}Adding a Field:
# Old entities don't need migration - just use default
curl -X GET http://localhost:8080/entities/users:alice
# Check if 'bio' exists, use default if notChanging Field Type:
# Migrate string ID to integer
def migrate_user_ids():
users = query_all_users()
for user in users:
old_id = user['attributes']['id'] # String
new_id = int(old_id) # Integer
user['attributes']['id'] = new_id
update_entity(user)Splitting an Entity:
# Split user entity into user + profile
def split_user_profile():
users = query_all_users()
for user in users:
# Create new profile entity
profile = {
"entity_id": f"profiles:{user['entity_id'].split(':')[1]}",
"attributes": {
"bio": user['attributes'].get('bio'),
"avatar": user['attributes'].get('avatar')
}
}
create_entity(profile)
# Remove profile fields from user
del user['attributes']['bio']
del user['attributes']['avatar']
update_entity(user)-
Design for queries, not structure
- Understand access patterns first
- Optimize for common queries
-
Use namespaces consistently
users:* products:* orders:* -
Denormalize read-heavy data
- Display names
- Counts and aggregates
- Frequently accessed relationships
-
Version your schema
{ "entity_id": "users:alice", "schema_version": 2, "attributes": {...} } -
Monitor and iterate
- Start simple
- Add indexes as needed
- Refactor based on metrics
-
Don't over-normalize
- Causes excessive joins
- Poor read performance
-
Don't create indexes blindly
- Each index slows writes
- Only index queried columns
-
Don't store large BLOBs in entities
- Keep entities < 1MB
- Store large files separately
-
Don't ignore data growth
- Plan for partitioning
- Archive old data
Before going to production:
- Analyzed access patterns
- Created indexes on queried columns
- Tested with realistic data volumes
- Monitored query performance
- Implemented caching strategy
- Planned for data growth
- Documented schema design decisions
- β Multi-model design principles
- β Normalization vs. denormalization trade-offs
- β Index strategy and placement
- β Real-world schema patterns
- β Migration strategies
- β Performance optimization
- Best Practices Guide - Production patterns
- Performance Guide - Optimization techniques
- Try Examples: Build a CRM or E-Commerce
Questions? Ask in GitHub Discussions
ThemisDB 1.9.0-beta Β· Home Β· Module-Index Β· GitHub Β· Issues
ThemisDB 1.9.0-beta Β· Home Β· Wiki-Index Β· Module-Index Β· FAQ Β· Quick-Reference Β· GitHub Β· Issues Β· Discussions Β· License
- Batch Operations
- Best Practices
- CRUD Tutorial
- Custom Document Ingestion
- Getting Started Tutorial
- Interactive Examples
- Schema Design
- Video Tutorials
- AQL Reference
- AQL Examples
- AQL Overview
- AQL Feature Roadmap
- AQL Geospatial Guide
- AQL LLM Migration Guide
- AQL API
- AQL Grammar (EBNF)
- AQL Root Overview
- AQL Examples (root)
- API Reference
- API Module README
- OpenAPI Overview
- Client SDK Overview
- SDK Overview
- Operations
- Operations Overview
- Operations Runbook
- Operations Handbook
- ThemisCtl Admin Guide
- Pipeline E2E SOPs
- Deploy Overview
- Docker Overview
- Docker Hub README
- Helm Overview
- Packaging Overview
- Operator Overview
- Security Policy
- Production Hardening Checklist
- Security Hardening Guide
- Encryption Key Management
- Access Control Framework
- Zero Trust Policy
- API Authentication & Authorization
- HSM Production Setup
- PKCS11 Integration
- DSGVO / SOC2 Checklist
- Access Model Runbooks
- Access Model Dashboard
- Maturity Automation Runbook
- Access Review Automation
- Access Model Dashboard
- Access Model Runbooks
- Rights Revocation
- Dr Checklists
- Dr Testing
- Incident Response Playbook
- Incident Response Testing
- GPU Oom Recovery
- Grammar Debugging
- Metrics Scrape Troubleshooting
- Model Swap Procedure
- Quota Tuning
- Subagent Deployment
- Logging Configuration
- Content Model
- Crypto & Keys
- Feature Flags Reference
- Modular Architecture Roadmap
- Modularization Guide
- Module Architecture Index
- PostgreSQL Wire Protocol
- Query Scheduling
- Raft Consensus Design
- Resource Pooling
- Source Directory Guide
- Unified Access Model
- E1 001 Layered Retrieval Design
- E1 002 Ann Abstraction Strategy
- E1 003 Tensor Summary Types
- E1 004 Lora Package Distinction
- E1 005 Model Switch Compatibility
- E1 006 Federated Tensor Summaries
- E2 001 Evaluation Framework Design
- E2 002 Hardware Profile Strategy
- E2 003 Query Planner Routing Model
- E2 004 Approximation Governance Rules
- E2 005 Cross Layer Fallback Confidence Policy
- E3 001 Distributed Tensor Design
- E3 002 Manifest Coordination Strategy
- E3 003 Recovery And Erasure Choice
- E3 004 Tensor Fabric Infrastructure
- Contributing
- Contributing (root)
- Code of Conduct
- Support
- Maintainers
- CTest Guide
- Build Quick Reference
- Developer Wiki Index
- Build / Test / CI
- Module Index
- Branching Strategy
- Disabled Stub Policy
- Docs PR Policy
- GA Promotion Sign Off
- Github Milestones Setup
- Maturity Claim Verification Checklist
- Maturity Evidence Registry
- Merge Gate Bot Config
- Merge Gate Status Live
- Phase 1 Closure Report
- Phase Closure Policy
- Phase Dependency Graph
- Phase3 Enforcement Runbook
- Plugin Submodule Rollback
- PR Version Targeting
- PR Version Targeting Backfill
- Production Ready 2026 Delivery Plan
- Query Module Status
- Readme
- Release Promotion Gate Policy
- Release Validation Checklist
- Security Module 5671 Evidence Summary
- Sharding P6 Residual Risk Acceptance
- Sourcecode Compliance Governance
- Updates Development Status Sign Off
- Wave C Implementation Complete
- Blob Storage
- Cuda
- Ethics Ai
- Exporters
- Huggingface
- Image Analysis
- Importers
- RPC
- Scraper
- Themisdb Ai Watermark Detector
- User Storage Encrypted
- Chimera Architecture
- Chimera Future
- Chimera Readme
- Chimera Roadmap
- Covina Fastapi Ingestion Architecture
- Covina Fastapi Ingestion Future
- Covina Fastapi Ingestion Roadmap
- Vcc Base Architecture
- Vcc Base Future
- Vcc Base Roadmap
- Vcc Clara Ingestion Architecture
- Vcc Clara Ingestion Future
- Vcc Clara Ingestion Roadmap
- Vcc Veritas Architecture
- Vcc Veritas Future
- Vcc Veritas Roadmap
- 01 Hello World
- 02 Todo App
- 03 Contact Manager
- 04 Inventory System
- 05 Time Series Monitor
- 06 Graph Social Network
- 07 Vector Search Documents
- 08 Dms Erp System
- 09 Iot Sensor Network
- 10 Drone Image Analysis
- 11 Blog Wiki
- 12 Expense Tracker
- 13 Recipe Manager
- 14 Ecommerce Catalog
- 15 Event Management
- 16 Kanban Board
- 17 Crm
- 18 Realtime Chat
- 19 Recommendation Engine
- 20 Smart Home
- 21 Coding Platform
- 22 AQL Diagram Tool
- 23 Traveling Salesman
- 24 Moral Philosophy Debates
- API Versioning
- Distributed Sharding
- Feedback Plugins
- Geo
- Gnn
- Image Analysis
- Legal Lora Training
- LLM
- Lora Sync
- Migration
- Nlp
- Performance
- Railway
- Replication
- Rope Visualization
- Sample Product Config
- Security
- Client SDK Overview
- Quickstart
- Sdk Enhancements
- Sdk Implementation Summary
- Test Suite Readme
- Go
- Java
- Javascript
- Php
- Python
- Ruby
- Rust
- Typescript
- 01 Grundlegende Operationen
- 02 AQL Queries
- 03 Graph Daten
- 04 Multimodell Anwendung
- 01 Quickstart Guide
- 02 AQL Referenz Kurzuebersicht
- 03 Datenmodellierung Guide
- 04 Uebungsaufgaben
- 05 Best Practices Guide
- Training Documents
- Training Overview
- 01 Einfuehrung Und Uebersicht
- 02 Datenmodelle Und Architektur
- 03 AQL Abfragesprache
- 04 Installation Und Setup
- 05 Anwendungsbeispiele
- Training Presentations
- Dependencies Readme
- Processmonitor Readme
- Themis.admintools.shared Readme
- Themis.aqlquerybuilder Readme
- Themis.aqlquerybuilder Roadmap
- Themis.auditlogviewer Readme
- Themis.auditlogviewer Roadmap
- Themis.classificationdashboard Readme
- Themis.classificationdashboard Roadmap
- Themis.compliancereports Readme
- Themis.compliancereports Roadmap
- Themis.gisviewer.controlpanel Readme
- Themis.gisviewer.controlpanel Roadmap
- Themis.impactanalysisviewer Readme
- Themis.impactanalysisviewer Roadmap
- Themis.ingestiontool Readme
- Themis.ingestiontool Roadmap
- Themis.keyrotationdashboard Readme
- Themis.keyrotationdashboard Roadmap
- Themis.piimanager Readme
- Themis.piimanager Roadmap
- Themis.retentionmanager Readme
- Themis.retentionmanager Roadmap
- Themis.sagaverifier Readme
- Themis.sagaverifier Roadmap
- Themis.usbadmintool Readme
- Themis.usbadmintool Roadmap
- CI Readme
- CI Roadmap
- Compiler Diagnostics Readme
- Compiler Diagnostics Roadmap
- Completion Readme
- Copilot Ollama Router Readme
- Copilot Ollama Router Roadmap
- Gnn Readme
- Gnn Roadmap
- Rope Visualizer Readme
- Rope Visualizer Roadmap
- Tco Calculator Readme
- Tco Calculator Roadmap
- Tests Readme
- Tests Roadmap
- Themis Config Wx Readme
- Themis Docs Builder Readme
- Wikipedia Ingestion Readme