stsdb开发指南
摘自:http://www.iopenworks.com/Products/ProductDetails/DevelopmentGuide?proID=387
多线程问题,请参见线程安全小结
1 STSdb存储引擎
STSdb存储引擎是一个基于瀑布树结构实现的NoSQL数据库和虚拟文件系统。该存储引擎提供两种数据结构——XIndex和XFile,一个存储引擎可以包含多个XIndex表和XFile文件。下面我们看一个简单示例。
2 简单示例
(1)打开数据库,创建表
using (StorageEngine engine =newStorageEngine("stsdb4.sys","stsdb4.dat")){XIndex<int,string> table = engine.OpenXIndex<int,string>("table");for(int i =0; i <1000000; i++){
table[i]= i.ToString();} table.Flush();
engine.Commit();}
(2)打开数据库,从表中读取数据
using (StorageEngine engine =newStorageEngine("stsdb4.sys","stsdb4.dat")){XIndex<int,string> table = engine.OpenXIndex<int,string>("table");foreach(var row in table)//table.Forward(), table.Backward(){Console.WriteLine("{0} {1}", row.Key, row.Value);}}
3 XIndex
XIndex是一个按序的键/值对存储(表)。我们可以在同一个引擎使用不同的键/记录类型来读取多个普通的表。每一个表并没有列数量的特殊限制。
需要注意的是:在当前版本提交操作是在存储引擎这一级别的——engine.Commit(),它将提交对所有表的更新。在官方的Release版本,每一个表的Commit()方法也将可用。
3.1 XIndex<TKey, TRecord>泛型类支持的泛型类型
我们可以使用XIndex<TKey, TRecord> table来定义一个表。这里TKey和TRecord支持的类型有:
● 基本类型——Boolean、Char、SByte、Byte、Int16、UInt16、Int32、UInt32、Int64、UInt64、Single、Double、Decimal、DateTime、String、byte[];
● 包含默认构造器的类型和结构体,他们使用基本类型定义了公开的读/写属性。
● 包含默认构造器的类型和结构体,他们使用基本类型和上述使用基本类型定义的类/结构体定义了公开的读/写属性。
● 可以转换成IData接口的类型。
下面我们来看一个示例,我们定义了两个类型,对应于TKey和TRecord。
publicclassKey{publicstringSymbol{ get;set;}publicDateTimeTimestamp{ get;set;}}publicclassTick{publicdoubleBid{ get;set;}publicdoubleAsk{ get;set;}publiclongVolume{ get;set;}publicstringProvider{ get;set;}}
我们可以以以下方式来打开表。
XIndex<long,Tick> table1 = engine.OpenXIndex<long,Tick>("table1");XIndex<DateTime,Tick> table2 = engine.OpenXIndex<DateTime,Tick>("table2");XIndex<Key,Tick> table3 = engine.OpenXIndex<Key,Tick>("table3");
或者,甚至可以用以下方式。
XIndex<Tick,Tick> table4 = engine.OpenXIndex<Tick,Tick>("table4");
在使用组合键的情况下,存储引擎将会使用子键进行比较。
3.2 XIndex<TKey, TRecord> 类型定义的方法
XIndex<TKey,TRecord>实现了IIndex<TKey,TRecord>接口,它定义了如下的方法:
publicinterface IIndex<TKey,TRecord>:IIndex,IEnumerable<KeyValuePair<TKey,TRecord>>{TRecordthis[TKey key]{ get;set;}voidReplace(TKey key,TRecord record);voidInsertOrIgnore(TKey key,TRecord record);voidDelete(TKey key);voidDelete(TKey fromKey,TKey toKey);voidClear(); bool Exists(TKey key);
bool TryGet(TKey key,outTRecord record);TRecordFind(TKey key);TRecordTryGetOrDefault(TKey key,TRecord defaultRecord);KeyValuePair<TKey,TRecord>?FindNext(TKey key);KeyValuePair<TKey,TRecord>?FindAfter(TKey key);KeyValuePair<TKey,TRecord>?FindPrev(TKey key);KeyValuePair<TKey,TRecord>?FindBefore(TKey key);IEnumerable<KeyValuePair<TKey,TRecord>>Forward();IEnumerable<KeyValuePair<TKey,TRecord>>Forward(TKeyfrom, bool hasFrom,TKey to, bool hasTo);IEnumerable<KeyValuePair<TKey,TRecord>>Backward();IEnumerable<KeyValuePair<TKey,TRecord>>Backward(TKey to, bool hasTo,TKeyfrom, bool hasFrom);KeyValuePair<TKey,TRecord>FirstRow{ get;}KeyValuePair<TKey,TRecord>LastRow{ get;}longCount();}
默认的XIndex迭代器使用升序方式遍历了表中的每一行。
Forward()方法以升序遍历表的每一行。
Backward()方法以降序遍历表的每一行。
FindNext()返回大于等于指定Key的第一行。
FindAfter()返回大于指定Key的第一行。
FindPrev()返回小于等于指定Key的第一行。
FindBefore()返回小于指定Key的第一行。
FirstRow返回最小Key的行。
LastRow返回最大Key的行。
以下方法用于异步更改XIndex的内容,他们在瀑布树中执行相应的操作。
this[TKey key]set;Replace(TKey key,TRecord record);InsertOrIgnore(TKey key,TRecord record);Delete(TKey key);Clear().
3.3 XIndex<TKey, TRecord>基础知识
前面已经提过,每一个存储引擎可以使用不同的类型处理多个XIndex<TKey,TRecord>表。每一个TKey和TRecord可以是基本类型或者复杂结构体或者类型。然而,在所有情况,每一个泛型的XIndex都使用一个非泛型的XIndex表来存储它的数据,如下所示。
public class XIndex : IIndex<IData, IData>
当一个XIndex被创建,它使用.NET表达式自动生成和编译能够将每一个TKey和TRecord实例转换成一个合适的IData实例的转换代码。因此,从一个数据库的角度来看,XIndex<TKey, TRecord>好像是在XIndex中实现了应用层数据和内部数据的转换。这确保了内部存储的独立,而依赖于应用定义的类型,同时为以更自然的方式向开发者提供了使用自定义类型的存储。
3.4 XIndex和IData实现
XInde使用如下由STSdb实现的IData类型。
publicinterface IData{}publicclassData<TSlot0>:IData{publicTSlot0Slot0;}publicclassData<TSlot0,TSlot1>:IData{publicTSlot0Slot0;publicTSlot1Slot1;}publicclassData<TSlot0,TSlot1,TSlot2>:IData{publicTSlot0Slot0;publicTSlot1Slot1;publicTSlot2Slot2;}...
当前版本支持最多64个Slot的Key和Record的Data类型。每一个Slot可以是任何基本类型。
以下代码演示了如何直接使用非泛型XIndex。
//writing
using (StorageEngine engine =newStorageEngine("stsdb4.sys","stsdb4.dat")){XIndex table = engine.OpenXIndex(typeof(Data<int>),typeof(Data<string>),"table");for(int i =0; i <1000000; i++){
table[newData<int>(i)]=newData<string>(i.ToString());} table.Flush();
engine.Commit();}
//reading
using (StorageEngine engine =newStorageEngine("stsdb4.sys","stsdb4.dat")){XIndex table = engine.OpenXIndex(typeof(Data<int>),typeof(Data<string>),"table");foreach(var row in table)//table.Forward(), table.Backward(){Data<int> key =(Data<int>)row.Key;Data<string> record =(Data<string>)row.Value;Console.WriteLine("{0} {1}", key.Slot0, record.Slot0);}}
3.5 数据转换
数据转换用于实现将应用定义的类型与IData类型的转换。他们构建了XIndex<TKey, TRecord>和XIndex表的转换层。所有的转换都实现了如下接口。
publicinterface IDataTransformer<T>{IDataToIData(T item);
T FromIData(IData data);DataDescriptorDataDescriptor{ get;}}
每一个XIndex<TKey, TRecord>示例自动生成两个数据转换——一个用于实现Key的转换,另一个实现Record的转换。也就是说,每一个输入的TKey/TRecord实例将转换成合适的IData实例。同样的,来自于XIndex的每一个IData实例也将转换到TKey/TRecord实例(在一些很复杂的情况,可以由自己来定义转换)。
假设我们定义了以下类型。
publicclassTick{publicstringSymbol{ get;set;}publicDateTimeTimestamp{ get;set;}publicdoubleBid{ get;set;}publicdoubleAsk{ get;set;}publiclongVolume{ get;set;}publicstringProvider{ get;set;}}
并且我们定义了XIndex<long, Tick>。
XIndex<long,Tick> table = engine.OpenXIndex<long,Tick>("table");
那么,在后端的XIndex表将使用以下两个对应于键和记录的类型。
Data<long>Data<string,DateTime,double,double,long,string>
我们可以用以下代码来模拟打开后端的XIndex表。
XIndex table2 = engine.OpenXIndex(typeof(Data<long>),typeof(Data<string,DateTime,double,double,long,string>),"table");
在上述的例子,table和table2将指向相同的数据。
如果我们希望使用非基本类型来扩展Tick类,比如。
publicclassProvider{publicstringName{ get;set;}publicstringWebsite{ get;set;}}publicclassTick{publicstringSymbol{ get;set;}publicDateTimeTimestamp{ get;set;}publicdoubleBid{ get;set;}publicdoubleAsk{ get;set;}publiclongVolume{ get;set;}publicProviderProvider{ get;set;}}
那么,此时后端的XIndex可以使用以下类型来打开。
Data<long>Data<string,DateTime,double,double,long, bool,string,string>
我们还可以使用Symbol和Timestamp并使用它作为组合键。
publicclassKey{publicstringSymbol{ get;set;}publicDateTimeTimestamp{ get;set;}}publicclassProvider{publicstringName{ get;set;}publicstringWebsite{ get;set;}}publicclassTick{//public string Symbol { get; set; }//public DateTime Timestamp { get; set; }publicdoubleBid{ get;set;}publicdoubleAsk{ get;set;}publiclongVolume{ get;set;}publicProviderProvider{ get;set;}}
XIndex<Key,Tick> table = engine.OpenXIndex<Key,Tick>("table");
此时后端的XIndex可以使用以下类型来打开。
Data<string,DateTime>Data<double,double,long, bool,string,string>
需要注意的是,因为每一个数据Slot只能由基本类型来定义,因此,需要使用一个额外的Boolean Slot来指定引用类型的对象的属性是否为null。这样,我们可以拆分自定义类型。
如果一个XIndex使用了组合Key,这些Key使用了不止一个Slot,那么数据引擎将使用BigEndian按照从小到大的Slot的顺序来比较子键。
转换成IData后,用户的数据非常适合于压缩。该引擎能够为每一个XIndex类型自动生成压缩类。这些压缩类依赖于Slot的基本类型为每一个Slot使用并行垂直方法的进行压缩。因此,压缩会很快并保持很高的压缩比。默认的,XIndex<TKey,TRecord>和XIndex以压缩的方式来保存数据。
4 XFile
STSdb 4.0支持稀疏文件存储,称为XFile。我们可以基于标准的.NET流来使用XFile。
using (StorageEngine engine =newStorageEngine("stsdb4.sys","stsdb4.dat")){XFile file = engine.OpenXFile("file");Random random =newRandom();byte[] buffer =newbyte[]{1,2,3,4,5,6,7,8,9,10};for(int i =0; i <100; i++){long position = random.Next();//writes some data on random positions
file.Seek(position,SeekOrigin.Begin);
file.Write(buffer,0, buffer.Length);} file.Flush();
engine.Commit();}
XFile使用特殊的XIndex<long, byte[]>实现且提供了更为高效的稀疏文件功能。这样,在一个存储引擎里,开发人员可以组合使用XIndex表和XFile文件。
5 线程安全
存储引擎是线程安全的,在一个存储引擎中使用不同线程创建XIndex和XFile实例是线程安全的。不过,XIndex和XFile本身不是线程安全的。在同一个存储引擎,不同的线程来处理由其创建的XIndex和XFile是线程安全的。
stsdb开发指南的更多相关文章
- ASP.NET Aries 开源开发框架:开发指南(一)
前言: 上周开源了Aries开发框架后,好多朋友都Download了源码,在运行过程里,有一些共性的问题会问到. 所以本篇打算写一下简单的开发指南,照顾一下不是太看的懂源码的同学,同时也会讲解一下框架 ...
- FreeMarker模板开发指南知识点梳理
freemarker是什么? 有什么用? 怎么用? (问得好,这些都是我想知道的问题) freemarker是什么? FreeMarker 是一款 模板引擎: 即一种基于模板和要改变的数据, 并用来生 ...
- Jetty使用教程(四:21-22)—Jetty开发指南
二十一.嵌入式开发 21.1 Jetty嵌入式开发HelloWorld 本章节将提供一些教程,通过Jetty API快速开发嵌入式代码 21.1.1 下载Jetty的jar包 Jetty目前已经把所有 ...
- JVM 平台上的各种语言的开发指南
JVM 平台上的各种语言的开发指南 为什么我们需要如此多的JVM语言? 在2013年你可以有50中JVM语言的选择来用于你的下一个项目.尽管你可以说出一大打的名字,你会准备为你的下一个项目选择一种新的 ...
- iOS原生地图开发指南续——大头针与自定义标注
iOS原生地图开发指南续——大头针与自定义标注 出自:http://www.sxt.cn/info-6042-u-7372.html 在上一篇博客中http://my.oschina.net/u/23 ...
- Angularjs中文版本开发指南发布
从本人开始在写关于Angularjs的文章开始,也算是见证了Angularjs在国内慢慢的火起来,如今的Angularjs正式如日中天.想知道为什么Angularjs会这么火,请移步angularjs ...
- nodejs开发指南读后感
nodejs开发指南读后感 阅读目录 使用nodejs创建http服务器; supervisor的使用及nodejs常见的调式代码命令了解; 了解Node核心模块; ejs模板引擎 Express 理 ...
- Libgdx 开发指南——目录
本系列文档选译自libgdx github项目 wiki : https://github.com/libgdx/libgdx/wiki 由于关于Libgdx的中文文档非常稀缺,因此在这里对官方Wik ...
- jQuery MiniUI 开发指南+API组件参考手册
jQuery MiniUI 开发指南 本文档将逐步的讲解jQuery MiniUI的方方面面,从此您将踏上jQuery MiniUI的深入探索之旅. 1.Hello M ...
随机推荐
- 实验室ip同步脚步
#!/bin/bash PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin hostname=`hostname` us ...
- git 分批后的数据
如果涉及到大文件的 git 传输, 我们可能会收到下面错误: sourceTree 的错误. 命令行的错误: $ git clone https://********/gopher.git C ...
- quartus II PIN脚相关之一
FPGA设计中有时候会改变输入输出名称,但是会带来一个问题,在PIN 叫配置页面上会有余留的久名称的Pin脚.如实例中,把 FPGA_CLK_50MHZ 名称修改为 FPGA_CLK,经过编译综合之后 ...
- 创建线程方式-NSOperation
*:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...
- set JAVA_HOME in RHEL/CentOS
3.3. Install OpenJDK on Red Hat Enterprise Linux Introduction OpenJDK is one of many Java Developmen ...
- EBS应用服务器启动指南
1.ssh应用服务器 applprod用户密码:*** 管理脚本在$ADMIN_SCRIPTS_HOME路径下 adstrtal.sh 启动所有服务,命令行为adstrtal.sh ...
- nodejs将PDF文件转换成txt文本,并利用python处理转换后的文本文件
目前公司Web服务端的开发是用Nodejs,所以开发功能的话首先使用Nodejs,这也是为什么不直接用python转换的原因. 由于node对文本的处理(提取所需信息)的能力不强,类似于npm上的包: ...
- 删除sde用户问题
删除SDE用户(GIS地图数据用户),长时间删除没反应,结束drop user sde cascade命令后,重新执行,结果报ORA-00604 ORA-21700 select user_id,us ...
- VS2012调试时无法启动程序和拒绝访问问题汇总
很多人在使用VS2012的时候会出现下面所示的问题,我也是,而且不止一次,也不是同样的问题,我这里就把一些常见的解决方法罗列一下.
- Android之使用Android-AQuery异步加载图片(一)
第一节:转载地址(http://www.cnblogs.com/lee0oo0/archive/2012/10/25/2738299.html) // 必须实现AQuery这个类 AQuery aq ...