Description
iBoxDB is a fast acid table-style document NoSQL Embedded Database, easily store objects and documents, traditional table with unstructured data, zero configuration, pure JAVA and DotNET engines, no dependencies.
iBoxDB has a well designed interface with great performance and capability for agile development. You can create applications with database services embedded and deploy it on mobiles, desktops, servers, to locally persist your data from anywhere.
Green, low carbon emission!
Dual Core Application Database
For JAVA C# Android Unity Xamarin Mono Linux Windows
Features
- CRUD and Forward CRUD
- KeyValue and KeyOnly tables
- Unique and non-unique indexes
- Unique and non-unique composite indexes
- SQL like query language
- Transactions support
- Concurrency control, thread safe
- Multiple applications supported
- Memory management
- Programmable replication
- Hot mirror copy
- On disk and in memory databases supported
- Automatically create databases
- Zero configuration, copy and run, purely managed code
- Dynamic columns
- Prototype columns
- Different types with different indexes can be stored in same table
- Persistence + ORM + Cache + Embeddable, ONE STOP solution
- Ason, Array Script Object Notation
- High performance, no dependencies
- Transaction Huggers
- Directly Select
- Update Increment
- Selecting Tracer
- Snapshot-Serializable Isolation
- Benchmark Anytime
- JAVA6+ .NET2+
Examples, CSharp and Java
Each box is an ISOLATED data space (transaction-based)
using(var box = auto.Cube())
{
//select, insert, update, delete ...
//replace()=(insert or update)
CommitResult cr = box.Commit();
}
try(Box box = auto.cube()){
...
CommitResult cr = box.commit();
}
Advertising
Digital life starts here, record every parameter guided to memorable moment.
Normal Object
Member m = new Member();
m.Id = box.NewId();
m.Name = "Andy";
m.Password = EncodePassowrd("123");
box["Member"].Insert(m);
Member m = new Member();
m.Id = box.newId();
m.Name = "Kevin";
box.d("Member").insert(m);
Dynamic Object (document database)
//Game : Dictionary<string, object>
game["GameType"] = "ACT";
box["Product"].Insert(game);
//Game extends HashMap<String,Object>
game.put("GameType", "ACT");
box.d("Product").insert(game);
Key Value Style Query
box["Table", 2L].Select<Member>();
//Composite Key
box["Table2", 99, "ABC"].Select<Product>();
box.d("Table", 3L).select(Member.class);
//Composite Key
box.d("Table2", 88, "ABC").select(Product.class);
Composite Key Supported
config.ensureTable(Item.class, "Item", "UID", "Type")
SQL Like
/*
from TABLE where A>? & B<=? order by C limit 0,10
from [table] where [condition]
order by [field1] desc,[field2] limit [0,10]
[Condition:] == != < <= > >= & | ( )
*/
box.Select<Member>("from Member where Name==?", "MyName");
box.select(Member.class, "from Member where Name==?", "MyName");
Query
//query
box.Select("from Member");
Query Options
//load to memory first, startswith '*'.
//because the OS has read-ahead setting,
//normally don't need to load first.
box.Select("*from Member");
//selecting tracer, startswith '!'
box.Select("!from Member");
Weak Object
//Strongly typed
box.select("from Table where Id > ?" , 1L);
//Weak Object
box.select("from Table where Id > ?" , new Variant("1"));
Index, make Select hundred times faster in average
//Index
config.EnsureIndex<Member>("Member", "Field1")
config.ensureIndex(Member.class, "Member", isUnique,"Field1")
//Composite-Index
config.EnsureIndex<Member>("Member", "Field1","Field2")
config.ensureIndex(Member.class, "Member", isUnique,"Field1","Field2")
//Both can speed up Search, free to choose one of them.
//only one Index will be selected in one Search,
//adding both to one Search will waste.
//Index is generic, and fast enough.
//Composite-Index mostly used in equal-and-equal scenario
box.Select("from Member where Field1 == ? & Field2 == ?",arg1,arg2)
//Id on the Left would faster in many cases
box.Select("from Member where Id == ? & Field == ?",id,arg)
//Key is primary Index, can create composite Index with Key
//but Key is unique, the second field is rarely used
config.EnsureIndex(..., "Id","Field")
//switch the order might help in some cases
config.EnsureIndex(..., "Field","Id")
//see detail of Array comparison
//KeyValue databases always have Key
//combining Results would faster than OR,
//depends on the scale of dataset and corresponded Index configure.
//where Id == ? | Id == ? | Id == ?
foreach(var id in [ 1, 2, 3 ])
combiner.Add( box.Select("from Member where Id == ?",id) )
Custom QueryFunction
box.Select<Member>("from Member where [Tags]", new IFunction("Value"))
Custom Object Table Binding
public bool Insert(Member m){
return auto.Insert(nameof(Member), m);
}
Compatible with LINQ (.NET)
from o in box.Select<Member>("from Member")
where o.Text.Contains(text) select o;
Compatible with Stream (Java)
StreamSupport
.stream(box.select(Member.class,"from Member").spliterator(), true)
.collect(groupingBy(m -> m.group, summarizingLong(m -> m.value)))
Ason and Prototype Columns
//define prototype, Id is Long
Ason prototype = new Ason("Id:", 0L, "Name:", "Guest");
Ason record = prototype.select();
//set Id as String,
record.set("Id", "123");
//will automatically convert to Long as the prototype
System.out.println("Output: " + record.get("Id").getClass());
//Output: class java.lang.Long
Hot Mirror Copy
auto.GetDatabase().CopyTo(bakAddr, bakRoot, buffer)
Directly Select
//Select records from a samll file directly
//without initializing database
IEnumerable records = DB.Select(fileAddress)
Transaction Huggers
//Three transactions committed together
long huggersBuffer = 1024L * 1024L * 32L;
box1.Commit(huggersBuffer);
box2.Commit(huggersBuffer);
box3.Commit();
Programmable Replication
//Master-Master
BoxData.masterReplicate();
//Master-Slave
BoxData.slaveReplicate();
Snapshot-Serializable Transaction
Transaction Step | Isolation Level |
---|---|
Application Point | Snapshot |
Database Point | Serializable |
using(var box = auto.Cube()){
//Snapshot...
box.Commit( ()=>{
//Serializable...
});
}
Update Increment
Update Increment | Auto Increment | |
---|---|---|
Apply To | index | key |
Trigger | insert / update | insert |
Type | long | number |
Value From | database newId (MaxPos,1) | table max (ID)+1 |
Generator Time | serializable transaction commit | data insert, differed from commit order |
Selecting Tracer
Tracer | Locker | |
---|---|---|
Thread | non-blocked | blocked |
Usage | read / write different records | read / write same record |
IO
IO |
---|
|
Database Path
C# & JAVA, place outside IDE working directory can get better performance//different path has hugely different writing speed on VM.
//Create Directory before putting DB inside.
//new File(path).mkdirs();
//Directory.CreateDirectory(path)
IBoxDB.LocalServer.DB.Root("/data/")
Add this Database Path as Exclusion into Scan-System to get higher performance,
for example, System Defender.
ASP.NET Cross Platform
DB.Root(MapPath("~/App_Data/"))
Xamarin
DB.Root(System.Environment.GetFolderPath(
System.Environment.SpecialFolder.LocalApplicationData/Personal))
Unity3D
DB.Root(Application.persistentDataPath)
Android
DB.root(android.os.Environment.getDataDirectory()
.getAbsolutePath() + "/data/" + packageName + "/")
JSP WebApplication
@WebListener()
public class StartListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
String path = System.getProperty("user.home") + "/data/";
new File(path).mkdirs();
DB.root(path);
}
}
Godot
<PackageReference Include="iBoxDB" Version="" />
var dir = Godot.OS.GetUserDataDir();
dir = Path.Combine(dir, "DBROOT");
Directory.CreateDirectory(dir);
DB.Root(dir)
jMonkeyEngine
File dir = JmeSystem.getStorageFolder(StorageFolderType.Internal);
dir = new File(dir, "ProjectName");
dir = new File(dir, "DatabaseName");
dir.mkdir();
DB.root(dir.getAbsolutePath());
Getting Started
using IBoxDB.LocalServer;
var db = new DB();
db.GetConfig().EnsureTable<Record>("Table", "Id");
AutoBox auto = db.Open();
auto.Insert("Table", new Record { Id = 1L, Name = "Andy" });
var record = auto.Get<Record>("Table", 1L);
record.Name = "Kelly";
auto.Update("Table", record);
auto.Delete("Table", 1L);
import iboxdb.localserver.*;
DB db = new DB();
db.getConfig().ensureTable(Record.class, "Table", "Id");
AutoBox auto = db.open();
auto.insert("Table", new Record(1L, "Andy"));
Record record = auto.get(Record.class, "Table", 1L);
record.Name = "Kelly";
auto.update("Table", record);
auto.delete("Table", 1L);
Memory Usage
DatabaseConfig cfg = db.getConfig();
//Cache Memory, set less 1/3 total
cfg.CacheLength = cfg.mb(1024L);
//Mobile Device 64MB
cfg.CacheLength = cfg.mb(64L);
//Read Pool, set 8+ to low Cache machine
cfg.ReadStreamCount = 8;
//Write Pool, set 4- to low Cache machine
cfg.WriteStreamCount = 1;
Install
.NET: Add NETDB/iBoxDB.DLL to Project
Java: Add JavaDB/iboxdb.jar to Project
Benchmark with MySQL
iBoxDB
Insert: 1,000,000 AVG: 47,016 objects/s
Update: 1,000,000 AVG: 25,558 objects/s
Delete: 1,000,000 AVG: 42,714 objects/s
MySQL
Insert: 1,000,000 AVG: 5,514 objects/s
Update: 1,000,000 AVG: 5,109 objects/s
Delete: 1,000,000 AVG: 6,044 objects/s
Benchmark Anytime
Locally benchmark the whole Application before every publishing as you wish. No expensive request units (RU/s).Supported Types
.NET | JAVA |
---|---|
|
|
Automatic Object Mapping | |
|
|
DatabaseConfig cfg;
//Create Table
ensureTable(Record.class, "Table", "Id");
//Create Index with length 32
ensureIndex(Record.class, "Table", "Name(32)");
//Indexing for byte[] or others,
//using ToBase64String(byte[]) Converts it to String.
.NET AOT Register Types
public static object Register
<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>()
where T : new()
{
return new T();
}
//Trigger DynamicallyAccessedMemberTypes.All
Register<T1>();
EnsureTable<T1>("T1", "Id");