• 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是线程安全的。

  • 相关阅读:
    基于Html5的移动应用开发经验总结:第一篇架构选型篇(下)
    401 Palindromes 解题报告
    uva 537 Artificial Intelligence?
    根据所给的年月,打印该月份的日历表
    八皇后问题
    uva10815 Andy's First Dictionary
    憋了我半天,写个博客发泄一下
    uva 457
    uva 10010 Where's Waldorf?
    uva424 Integer Inquiry
  • 原文地址:https://www.cnblogs.com/foreverme/p/3341101.html
Copyright © 2020-2023  润新知