Skip to content

Commit c7091e0

Browse files
author
MPCoreDeveloper
committed
optimized state 1
1 parent 8063b07 commit c7091e0

File tree

112 files changed

+23577
-898
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

112 files changed

+23577
-898
lines changed

README.md

Lines changed: 364 additions & 168 deletions
Large diffs are not rendered by default.
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
// <copyright file="BTreeIndexRangeQueryBenchmark.cs" company="MPCoreDeveloper">
2+
// Copyright (c) 2025-2026 MPCoreDeveloper and GitHub Copilot. All rights reserved.
3+
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
4+
// </copyright>
5+
6+
using BenchmarkDotNet.Attributes;
7+
using BenchmarkDotNet.Order;
8+
using SharpCoreDB.Benchmarks.Infrastructure;
9+
10+
namespace SharpCoreDB.Benchmarks;
11+
12+
/// <summary>
13+
/// Benchmarks B-tree index performance for range queries vs full table scan.
14+
/// Target: B-tree range query &lt; 10ms vs ~30ms full scan on 10k records.
15+
///
16+
/// Test Scenarios:
17+
/// 1. Full Table Scan (baseline) - SELECT * WHERE age &gt; 30
18+
/// 2. Hash Index Scan (control) - Falls back to full scan for range queries
19+
/// 3. B-Tree Range Query - SELECT * WHERE age &gt; 30 using B-tree index
20+
/// 4. B-Tree BETWEEN Query - SELECT * WHERE age BETWEEN 25 AND 35
21+
/// 5. B-Tree ORDER BY - SELECT * FROM users ORDER BY age (uses B-tree sorted iteration)
22+
///
23+
/// Expected Results:
24+
/// - Full scan: ~30ms (10k records, columnar storage)
25+
/// - Hash index: ~30ms (no benefit for range queries)
26+
/// - B-tree range: &lt; 10ms (3-5x faster with index)
27+
/// - B-tree BETWEEN: &lt; 15ms (selective range)
28+
/// - B-tree ORDER BY: &lt; 5ms (sorted iteration vs external sort)
29+
/// </summary>
30+
[MemoryDiagnoser]
31+
[Orderer(SummaryOrderPolicy.FastestToSlowest)]
32+
[RankColumn]
33+
public class BTreeIndexRangeQueryBenchmark
34+
{
35+
private BenchmarkDatabaseHelper? _dbFullScan;
36+
private BenchmarkDatabaseHelper? _dbHashIndex;
37+
private BenchmarkDatabaseHelper? _dbBTreeIndex;
38+
private const int RECORD_COUNT = 10_000;
39+
private const string DB_PATH_FULLSCAN = "./bench_btree_fullscan";
40+
private const string DB_PATH_HASH = "./bench_btree_hash";
41+
private const string DB_PATH_BTREE = "./bench_btree_btree";
42+
43+
[GlobalSetup]
44+
public void Setup()
45+
{
46+
// Clean up any existing test databases
47+
CleanupDatabase(DB_PATH_FULLSCAN);
48+
CleanupDatabase(DB_PATH_HASH);
49+
CleanupDatabase(DB_PATH_BTREE);
50+
51+
// Setup 1: Full scan (no indexes)
52+
_dbFullScan = new BenchmarkDatabaseHelper(DB_PATH_FULLSCAN, enableEncryption: false);
53+
_dbFullScan.CreateUsersTableColumnar();
54+
InsertTestData(_dbFullScan);
55+
56+
// Setup 2: Hash index (for comparison - should not help with range queries)
57+
_dbHashIndex = new BenchmarkDatabaseHelper(DB_PATH_HASH, enableEncryption: false);
58+
_dbHashIndex.CreateUsersTableColumnar();
59+
InsertTestData(_dbHashIndex);
60+
// Create hash index on age - won't help with range queries
61+
((SharpCoreDB.Database)((dynamic)_dbHashIndex).database)
62+
.ExecuteSQL("CREATE INDEX idx_age_hash ON users (age)");
63+
64+
// Setup 3: B-tree index (should significantly improve range queries)
65+
_dbBTreeIndex = new BenchmarkDatabaseHelper(DB_PATH_BTREE, enableEncryption: false);
66+
_dbBTreeIndex.CreateUsersTableColumnar();
67+
InsertTestData(_dbBTreeIndex);
68+
// Create B-tree index on age for range queries
69+
((SharpCoreDB.Database)((dynamic)_dbBTreeIndex).database)
70+
.ExecuteSQL("CREATE INDEX idx_age_btree ON users (age) USING BTREE");
71+
}
72+
73+
private void InsertTestData(BenchmarkDatabaseHelper db)
74+
{
75+
// Insert 10k records with ages distributed 18-65
76+
var users = new List<(int id, string name, string email, int age, DateTime createdAt, bool isActive)>();
77+
78+
for (int i = 1; i <= RECORD_COUNT; i++)
79+
{
80+
users.Add((
81+
id: i,
82+
name: $"User{i}",
83+
email: $"user{i}@example.com",
84+
age: 18 + (i % 48), // Ages 18-65
85+
createdAt: DateTime.UtcNow.AddDays(-i),
86+
isActive: i % 2 == 0
87+
));
88+
}
89+
90+
// Use true batch insert for fast setup
91+
db.InsertUsersTrueBatch(users);
92+
}
93+
94+
[GlobalCleanup]
95+
public void Cleanup()
96+
{
97+
_dbFullScan?.Dispose();
98+
_dbHashIndex?.Dispose();
99+
_dbBTreeIndex?.Dispose();
100+
101+
CleanupDatabase(DB_PATH_FULLSCAN);
102+
CleanupDatabase(DB_PATH_HASH);
103+
CleanupDatabase(DB_PATH_BTREE);
104+
}
105+
106+
private static void CleanupDatabase(string path)
107+
{
108+
try
109+
{
110+
if (Directory.Exists(path))
111+
{
112+
Directory.Delete(path, true);
113+
}
114+
}
115+
catch { /* Ignore cleanup errors */ }
116+
}
117+
118+
// ==================== RANGE QUERY BENCHMARKS ====================
119+
120+
[Benchmark(Baseline = true)]
121+
public void FullTableScan_RangeQuery()
122+
{
123+
// SELECT * FROM users WHERE age > 30
124+
// Expected: ~30ms (full scan of 10k records)
125+
var db = ((SharpCoreDB.Database)((dynamic)_dbFullScan!).database);
126+
var results = db.ExecuteQuery("SELECT * FROM users WHERE age > 30");
127+
128+
if (results.Count == 0)
129+
throw new InvalidOperationException("No results found - test data issue");
130+
}
131+
132+
[Benchmark]
133+
public void HashIndex_RangeQuery()
134+
{
135+
// SELECT * FROM users WHERE age > 30 (with hash index)
136+
// Expected: ~30ms (hash index doesn't help with range queries, falls back to scan)
137+
var db = ((SharpCoreDB.Database)((dynamic)_dbHashIndex!).database);
138+
var results = db.ExecuteQuery("SELECT * FROM users WHERE age > 30");
139+
140+
if (results.Count == 0)
141+
throw new InvalidOperationException("No results found - test data issue");
142+
}
143+
144+
[Benchmark]
145+
public void BTreeIndex_RangeQuery()
146+
{
147+
// SELECT * FROM users WHERE age > 30 (with B-tree index)
148+
// Expected: < 10ms (3-5x faster than full scan)
149+
var db = ((SharpCoreDB.Database)((dynamic)_dbBTreeIndex!).database);
150+
var results = db.ExecuteQuery("SELECT * FROM users WHERE age > 30");
151+
152+
if (results.Count == 0)
153+
throw new InvalidOperationException("No results found - test data issue");
154+
}
155+
156+
[Benchmark]
157+
public void BTreeIndex_BetweenQuery()
158+
{
159+
// SELECT * FROM users WHERE age BETWEEN 25 AND 35
160+
// Expected: < 15ms (selective range query)
161+
var db = ((SharpCoreDB.Database)((dynamic)_dbBTreeIndex!).database);
162+
var results = db.ExecuteQuery("SELECT * FROM users WHERE age >= 25 AND age <= 35");
163+
164+
if (results.Count == 0)
165+
throw new InvalidOperationException("No results found - test data issue");
166+
}
167+
168+
[Benchmark]
169+
public void BTreeIndex_OrderBy()
170+
{
171+
// SELECT * FROM users ORDER BY age
172+
// Expected: < 5ms (B-tree provides sorted iteration, no external sort needed)
173+
var db = ((SharpCoreDB.Database)((dynamic)_dbBTreeIndex!).database);
174+
var results = db.ExecuteQuery("SELECT * FROM users ORDER BY age");
175+
176+
if (results.Count != RECORD_COUNT)
177+
throw new InvalidOperationException($"Expected {RECORD_COUNT} results, got {results.Count}");
178+
}
179+
180+
[Benchmark]
181+
public void FullTableScan_OrderBy()
182+
{
183+
// SELECT * FROM users ORDER BY age (without B-tree index)
184+
// Expected: ~40ms (full scan + external sort overhead)
185+
var db = ((SharpCoreDB.Database)((dynamic)_dbFullScan!).database);
186+
var results = db.ExecuteQuery("SELECT * FROM users ORDER BY age");
187+
188+
if (results.Count != RECORD_COUNT)
189+
throw new InvalidOperationException($"Expected {RECORD_COUNT} results, got {results.Count}");
190+
}
191+
192+
// ==================== POINT LOOKUP COMPARISON ====================
193+
194+
[Benchmark]
195+
public void HashIndex_PointLookup()
196+
{
197+
// SELECT * FROM users WHERE age = 30 (with hash index)
198+
// Expected: < 1ms (O(1) hash lookup)
199+
var db = ((SharpCoreDB.Database)((dynamic)_dbHashIndex!).database);
200+
var results = db.ExecuteQuery("SELECT * FROM users WHERE age = 30");
201+
}
202+
203+
[Benchmark]
204+
public void BTreeIndex_PointLookup()
205+
{
206+
// SELECT * FROM users WHERE age = 30 (with B-tree index)
207+
// Expected: ~2ms (O(log n) B-tree lookup, slower than hash but still fast)
208+
var db = ((SharpCoreDB.Database)((dynamic)_dbBTreeIndex!).database);
209+
var results = db.ExecuteQuery("SELECT * FROM users WHERE age = 30");
210+
}
211+
}

0 commit comments

Comments
 (0)