STSdb 4.0 是一个开源的NoSQL 数据库和虚拟文件系统,支持实时索引,完全用c#开发的。
引擎原理基于WaterfallTree(瀑布树)数据结构搭建
以下内容基于stsdb4.dll(4.0.3.0版本)库 , 官方地址:http://stsdb.com/
1 using System; 2 using System.Collections.Generic; 3 4 namespace STSDB 5 { 6 [Serializable] 7 public class TStudent 8 { 9 public TStudent() 10 { 11 } 12 public string Name { get; set; } 13 public int Age { get; set; } 14 public int GroupNumber { get; set; } 15 public List<TCourse> CourseList { get; set; } 16 } 17 } 18 using System; 19 20 namespace STSDB 21 { 22 [Serializable] 23 public class TCourse 24 { 25 public string CourseName { get; set; } 26 public string Teacher { get; set; } 27 public int Score { get; set; } 28 } 29 } 30 演示代码: 31 /* 32 * 1. STSdb 4.0 是一个开源的NoSQL 数据库和虚拟文件系统,支持实时索引,完全用c#开发的。 33 * 引擎原理基于WaterfallTree(瀑布树)数据结构搭建 34 * 35 * 36 * 2.特性 37 * 支持几十亿级别的数据存取 38 * 支持TB级别文件大小 39 * 实时索引 40 * 内置压缩 41 * 内置序列化 42 * 支持稀疏分散的文件(byte[]) 43 * 存储内存可控 44 * 支持多线程,且线程安全 45 * Storage engine instance is thread-safe. Creating (opening) XTable and XFile instances in one storage engine from 46 different threads is thread-safe. 47 XTable and XFile instances are also thread-safe. Manipulating different XTable/XFile instances from different threads 48 is thread-safe. 49 * 50 * 3.缺点 51 * 不支持事务 52 * 同时处理所有打开的表 53 * 54 * 支持多种情况下的数据引擎连接 55 IStorageEngine engine = STSdb.FromMemory(); //从内存中读取 56 IStorageEngine engine = STSdb.FromStream(stream); //从数据流中读取 57 IStorageEngine engine = STSdb.FromHeap(heap); //从堆栈中读取 58 IStorageEngine engine = STSdb.FromNetwork(host, port); //从远程地址读取 59 60 * 61 * 62 */ 63 64 using System; 65 using System.IO; 66 using System.Linq; 67 using System.Collections.Generic; 68 69 namespace STSDB 70 { 71 using Newtonsoft.Json; 72 using STSdb4.Data; 73 using STSdb4.Database; 74 using STSdb4.Storage; 75 using STSdb4.WaterfallTree; 76 using STSdb4.Remote.Heap; 77 78 class Program 79 { 80 static void Main(string[] args) 81 { 82 ExecuteCode(WriteData); 83 ExecuteCode(ReadData); 84 //ExecuteCode(DatabaseSchemeInfo); 85 86 //ExecuteCode(ReadItem); 87 //ExecuteCode(DeleteItems); 88 //ExecuteCode(ReadItem); 89 90 //ExecuteCode(GetRecord); 91 //ExecuteCode(PageRecord); 92 93 //ExecuteCode(Others); 94 //ExecuteCode(ReNameTable); 95 96 //ExecuteCode(ExistsTable); 97 //ExecuteCode(DeleteTable); 98 //ExecuteCode(ExistsTable); 99 100 #region test 101 //bool quit = false; 102 //while (!quit) 103 //{ 104 // Console.Write("get item data: "); 105 // string demo = Console.ReadLine(); 106 // switch (demo) 107 // { 108 // case "Y": 109 // break; 110 // case "Q": 111 // quit = true; 112 // break; 113 // default: 114 // Console.WriteLine("Choose a Word between Y and Q(to quit)"); 115 // break; 116 // } 117 //} 118 #endregion 119 120 Console.ReadKey(); 121 } 122 /// <summary>执行方法</summary> 123 static void ExecuteCode(Action act) 124 { 125 System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch(); 126 stopwatch.Start(); 127 128 act(); 129 130 stopwatch.Stop(); 131 TimeSpan timespan = stopwatch.Elapsed; 132 133 Console.WriteLine("运行{0}秒", timespan.TotalSeconds); 134 } 135 136 /// <summary> 137 /// 数据库名 138 /// </summary> 139 /// <remarks>文件名和扩展名不限制</remarks> 140 protected static string DataBase = "ClassDB.db"; 141 /// <summary> 142 /// 学生表名 143 /// </summary> 144 protected static string TableName = "tb_student"; 145 /// <summary> 146 /// 【新】学生表名 147 /// </summary> 148 protected static string NewTableName = "new_tb_student"; 149 /// <summary> 150 /// XFile 151 /// </summary> 152 protected static string XFileName = "tb_file"; 153 154 #region 基本操作 155 /// <summary> 156 /// 创建库,写入数据 157 /// </summary> 158 static void WriteData() 159 { 160 /* 161 * ①:没有数据库会自动创建的,默认目录和应用程序目录一致; 162 * ②:打开表,Key支持组合结构 => OpenXTable<TKey, TRecord> 163 */ 164 using (IStorageEngine engine = STSdb.FromFile(DataBase)) //① 165 { 166 var table = engine.OpenXTable<int, TStudent>(TableName); //② 167 //var table2 = engine.OpenXTable<TKey, TTick>("table2"); //支持key嵌套 168 for (int i = 0; i < 1000; i++) 169 { 170 table[i] = new TStudent 171 { 172 Name = "Jon_" + i.ToString(), 173 Age = new Random().Next(25, 30), 174 GroupNumber = i + (new Random().Next(310, 399)), 175 CourseList = new List<TCourse>() 176 { 177 new TCourse{ 178 CourseName="C#高级编程"+i.ToString(), 179 Teacher="老陈"+i.ToString(), 180 Score=80 181 }, 182 new TCourse{ 183 CourseName="C#函数式程序设计"+i.ToString(), 184 Teacher="老李"+i.ToString(), 185 Score=90 186 }, 187 new TCourse{ 188 CourseName="多线程实战应用"+i.ToString(), 189 Teacher="老张"+i.ToString(), 190 Score=95 191 }, 192 } 193 }; 194 } 195 engine.Commit(); 196 } 197 } 198 /// <summary> 199 /// 读取数据 200 /// </summary> 201 static void ReadData() 202 { 203 using (IStorageEngine engine = STSdb.FromFile(DataBase)) 204 { 205 var table = engine.OpenXTable<int, TStudent>(TableName); //ITable:IEnumerable对象 206 foreach (var item in table) 207 Console.WriteLine(JsonConvert.SerializeObject(item, Newtonsoft.Json.Formatting.Indented)); 208 209 Console.WriteLine(table.Count()); //TableName表中有100行数据 210 } 211 } 212 213 /// <summary> 214 /// 215 /// </summary> 216 static void DatabaseSchemeInfo() 217 { 218 using (IStorageEngine engine = STSdb.FromFile(DataBase)) //① 219 { 220 IDescriptor descriptor = engine[TableName]; 221 Console.WriteLine(descriptor.CreateTime.ToString("yyyy-MM-dd HH:mm:ss")); 222 Console.WriteLine(descriptor.ModifiedTime.ToString("yyyy-MM-dd HH:mm:ss")); 223 Console.WriteLine(descriptor.Name); 224 //ID是表的唯一标识id,表一旦创建,它就创建了,后面只要表在就不会修改 225 //重建表它会从新分配 226 Console.WriteLine(descriptor.ID); 227 228 //... 229 } 230 } 231 232 /// <summary> 233 /// 读取单条数据 234 /// </summary> 235 static void ReadItem() 236 { 237 using (IStorageEngine engine = STSdb.FromFile(DataBase)) 238 { 239 var table = engine.OpenXTable<int, TStudent>(TableName); //ITable: IEnumerable对象 240 //var item = table.FirstOrDefault(x => x.Key <= 15 && x.Key >= 10); //key是5的记录 241 //table[10]; 242 var item = table.FirstOrDefault(x => x.Key == 5); //key是5的记录 243 if (item.Value != null) 244 Console.WriteLine(JsonConvert.SerializeObject(item, Newtonsoft.Json.Formatting.Indented)); 245 else 246 Console.WriteLine("key = 5 的记录不存在!"); 247 //Console.WriteLine("10<= key <= 15 的记录不存在!"); 248 } 249 } 250 251 static void AddItems() 252 { 253 using (IStorageEngine engine = STSdb.FromFile(DataBase)) 254 { 255 var table = engine.OpenXTable<int, TStudent>(TableName); 256 //table[100] = new TStudent(){....}; 257 table.InsertOrIgnore(2, new TStudent()); 258 259 engine.Commit(); 260 } 261 } 262 263 /// <summary> 264 /// 删除表数据 265 /// </summary> 266 static void DeleteItems() 267 { 268 using (IStorageEngine engine = STSdb.FromFile(DataBase)) 269 { 270 var table = engine.OpenXTable<int, TStudent>(TableName); //ITable:IEnumerable对象 271 if (table != null) 272 { 273 //table.Clear(); //清空表数据 274 table.Delete(5); //删掉key是5的记录 275 //table.Delete(10, 15); //删掉key从10到15的记录 276 engine.Commit(); //提交操作,不能少 277 } 278 } 279 } 280 281 /// <summary> 282 /// 按需获取数据 283 /// </summary> 284 static void GetRecord() 285 { 286 using (IStorageEngine engine = STSdb.FromFile(DataBase)) 287 { 288 /* 289 Forward向前读取, Backward向后读取, 它们都有2个重载,下面重点说明第二个重载 290 * Forward(TKey from, bool hasFrom, TKey to, bool hasTo); 291 * Backward(TKey to, bool hasTo, TKey from, bool hasFrom); 292 * 超出范围的都不会排除,另外,查询范围超出也不会有影响,但是要注意一点,formkey和endkey的大小关系 293 * 294 * 0<----------[(S)]----------------[(E)]------------->N 295 * 296 */ 297 var table = engine.OpenXTable<int, TStudent>(TableName); 298 var fiterTB = table.Forward(2, true, 9, true); //索引从2到9 299 //var fiterTB = table.Forward(2, false, 9, true); //索引从0到9 300 //var fiterTB = table.Forward(2, false, 9, false); //索引从0到表结尾 301 //var fiterTB = table.Forward(2, true, 9, false); //索引从2到表结尾 302 //Backward刚好相反 303 foreach (var item in fiterTB) 304 Console.WriteLine(JsonConvert.SerializeObject(item, Newtonsoft.Json.Formatting.Indented)); 305 } 306 } 307 /// <summary> 308 /// 数据分页 309 /// </summary> 310 static void PageRecord() 311 { 312 using (IStorageEngine engine = STSdb.FromFile(DataBase)) 313 { 314 int pageIndex = 2; 315 int pageSize = 10; 316 317 var table = engine.OpenXTable<int, TStudent>(TableName); 318 var fiterTB = table.Skip(pageSize * (pageIndex - 1)).Take(pageSize); 319 foreach (var item in fiterTB) 320 Console.WriteLine(JsonConvert.SerializeObject(item, Newtonsoft.Json.Formatting.Indented)); 321 } 322 } 323 /// <summary> 324 /// 文件数和记录数 325 /// </summary> 326 static void Others() 327 { 328 using (IStorageEngine engine = STSdb.FromFile(DataBase)) 329 { 330 //表和虚拟文件的数量 331 Console.WriteLine("数据库 " + DataBase + " 中有 {0} 张表:{1}", engine.Count, TableName); 332 333 //表记录数 334 var table = engine.OpenXTable<int, TStudent>(TableName); 335 Console.WriteLine("表" + TableName + "中有" + table.Count() + "条记录"); 336 } 337 } 338 339 /// <summary> 340 /// 表是否存在 341 /// </summary> 342 static void ExistsTable() 343 { 344 using (IStorageEngine engine = STSdb.FromFile(DataBase)) 345 { 346 //判断表存在与否 347 //bool exists = engine.Exists(NewTableName); 348 //Console.WriteLine(NewTableName + " exist?=>{0}", exists.ToString()); 349 350 bool exists = engine.Exists(TableName); 351 Console.WriteLine(TableName + " exist?=>{0}", exists.ToString()); 352 } 353 } 354 355 /// <summary> 356 /// 重命名表名 357 /// </summary> 358 static void ReNameTable() 359 { 360 using (IStorageEngine engine = STSdb.FromFile(DataBase)) 361 { 362 //判断表存在与否 363 bool exists = engine.Exists(TableName); 364 Console.WriteLine(TableName + " exist? =>{0}", exists.ToString()); 365 366 //表重命名 367 engine.Rename(TableName, NewTableName); 368 Console.WriteLine("表" + TableName + "被重命名为:" + NewTableName); 369 370 if (engine.Exists(TableName)) 371 Console.WriteLine("old table name \"" + TableName + "\" exist"); 372 if (engine.Exists(NewTableName)) 373 Console.WriteLine("new table name \"" + NewTableName + "\" exist"); 374 } 375 } 376 /// <summary> 377 /// 删除表 378 /// </summary> 379 static void DeleteTable() 380 { 381 using (IStorageEngine engine = STSdb.FromFile(DataBase)) 382 { 383 //删除表 384 engine.Delete(TableName); 385 //engine.Delete(NewTableName); 386 engine.Commit(); 387 } 388 } 389 #endregion 390 391 #region XFile 392 393 static void TestXFile() 394 { 395 using (IStorageEngine engine = STSdb.FromFile(DataBase)) 396 { 397 XFile file = engine.OpenXFile(XFileName); 398 399 Random random = new Random(); 400 byte[] buffer = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 401 402 for (int i = 0; i < 100; i++) 403 { 404 long position = random.Next(); 405 406 file.Seek(position, SeekOrigin.Begin); 407 file.Write(buffer, 0, buffer.Length); 408 } 409 engine.Commit(); 410 } 411 } 412 //XFile uses special XTable<long, byte[]> implementation to provide effective sparse file functionality. 413 //One storage engine can have many files 414 #endregion 415 416 #region Client/Server 417 418 static void ClientUpdateData() 419 { 420 using (IStorageEngine engine = STSdb.FromNetwork("localhost", 7182)) 421 { 422 ITable<int, string> table = engine.OpenXTable<int, string>("table"); 423 for (int i = 0; i < 100000; i++) 424 { 425 table[i] = i.ToString(); 426 } 427 engine.Commit(); 428 } 429 } 430 431 static void ServerHandleData() 432 { 433 string _dbname = "test.stsdb4"; 434 using (IStorageEngine engine = STSdb.FromFile(_dbname)) 435 { 436 var server = STSdb.CreateServer(engine, 7182); 437 server.Start(); 438 //server is ready for connections 439 //server.Stop(); 440 } 441 } 442 //The created server instance will listen on the specified port 443 //and receive/send data from/to the clients 444 445 #endregion 446 447 #region Memory Usage 448 /* 449 min/max children (branches) in each internal (non-leaf) node 450 max operations in the root node 451 min/max operations in each internal node 452 min/max records in each leaf node 453 number of cached nodes in the memory 454 */ 455 static void MemoryUsageHandle() 456 { 457 using (StorageEngine engine = (StorageEngine)STSdb.FromFile(DataBase)) 458 { 459 //下面的demo都是STS.DB的默认值设置 460 461 //min/max children (branches) in each internal node 462 engine.INTERNAL_NODE_MIN_BRANCHES = 2; 463 engine.INTERNAL_NODE_MAX_BRANCHES = 4; 464 //max operations in the root node 465 engine.INTERNAL_NODE_MAX_OPERATIONS_IN_ROOT = 8 * 1024; 466 //min/max operations in each internal node 467 engine.INTERNAL_NODE_MIN_OPERATIONS = 64 * 1024; 468 engine.INTERNAL_NODE_MAX_OPERATIONS = 128 * 1024; 469 //min/max records in each leaf node 470 engine.LEAF_NODE_MIN_RECORDS = 16 * 1024; 471 engine.LEAF_NODE_MAX_RECORDS = 128 * 1024; //at least 2 x MIN_RECORDS 472 //number of cached nodes in memory 473 engine.CacheSize = 32; 474 } 475 } 476 477 #endregion 478 479 #region Heap 480 481 /*using => 482 STSdb4.WaterfallTree; 483 STSdb4.Storage; 484 STSdb4.Remote.Heap; 485 */ 486 static void HeaperEngine() 487 { 488 //Server端 489 IHeap heap = new Heap(new FileStream("Heap.db", FileMode.OpenOrCreate)); 490 HeapServer server = new HeapServer(heap, 7183); //监听堆服务器 491 server.Start(); //开始监听 492 493 //从远程堆中创建 IStorageEngine 引擎,并处理数据 494 //using (IStorageEngine engine = STSdb.FromHeap(new RemoteHeap("host", 7183))) 495 //{ 496 // ITable<int, string> table = engine.OpenXTable<int, string>("table"); 497 // for (int i = 0; i < 100000; i++) 498 // { 499 // table[i] = i.ToString(); 500 // } 501 // engine.Commit(); 502 //} 503 } 504 #endregion 505 506 //... 507 508 } 509 }