浅析开源内存数据库Fastdb

介绍:

Fastdb是免费开源内存数据库,其优秀的性能,和简洁的C++代码,让我学习使用过程中收益颇多,但是国内中文相关研究的文章相当稀少,外文我查询相当不便。有兴趣的朋友可以通过以下网站访问:Main Memory Object-Relational Database Management System,相关文档详见:FastDB Main Memory Database Management System。本文将以Windows版本C++版本号3.76为基础进行开发和测试,听说有4.14的版本但是我没有办法获取,有获得新版本的朋友不妨能发我一份学习,我的邮箱:lyfwwb@163.com,在此先行感谢!本文将记录学习相关过程中心得和一些功能分析,希望自己不会忘记曾经使用过的历史和自己改造过程。借此机会给那些和我一样想用的朋友又碰到一样问题的人提供一些思路和方法。希望有人可以给我更好更完善的资料系统学习。很多人认为Fastdb只能本机上进行数据库操作,其实Fastdb在3.76版本中已经提供简单服务端/客户端功能了,有C++编程能力的可以实现更多的功能。框架作者已经做得很好了。

下面是Fastdb官方的介绍译文:

FastDB是一个高效的主存数据库系统,具有实时功能和方便的C++接口。FastDB不支持客户端-服务器体系结构,所有使用FastDB数据库的应用程序都应该在同一主机上运行。FastDB针对具有主导读取访问模式的应用程序进行了优化。通过消除数据传输开销和非常有效的锁定实现,可以提供高速的查询执行。数据库文件被映射到与数据库一起工作的每个应用程序的虚拟内存空间。因此,查询是在应用程序的上下文中执行的,不需要上下文切换和数据传输。并发数据库访问的同步是通过原子指令在FastDB中实现的,几乎不增加查询处理的开销。FastDB假设整个数据库都存在于RAM中,并根据这一假设优化搜索算法和结构。此外,FastDB没有数据库缓冲区管理引起的开销,并且不需要在数据库文件和缓冲池之间进行数据传输。这就是为什么FastDB的工作速度要比所有数据都缓存在缓冲池中的传统数据库快得多。

FastDB支持事务处理、在线备份和系统崩溃后的自动恢复。事务提交协议基于影子根页算法,执行数据库的原子更新。恢复可以非常快速地完成,为关键应用程序提供高可用性。此外,事务日志的消除提高了整个系统的性能,并使系统资源得到更有效的利用。

FastDB是一个面向应用程序的数据库。数据库表是使用有关应用程序类的信息构建的。FastDB支持自动方案评估,允许您只在一个地方进行更改——在应用程序类中。FastDB为从数据库中检索数据提供了一个灵活方便的接口。使用类似SQL的查询语言来指定查询。非原子字段、嵌套数组、用户定义的类型和方法、直接的对象间引用等后关系功能简化了数据库应用程序的设计,提高了它们的效率。

尽管FastDB是在假设数据库作为一个整体适合计算机的物理内存的情况下进行优化的,但也可以将其与数据库一起使用,因为数据库的大小超过了系统中物理内存的大小。在最后一种情况下,标准操作系统交换机制将起作用。但所有FastDB搜索算法和结构都是在所有数据都驻留在内存中的假设下进行优化的,因此交换数据的效率不会很高。

功能模块的分析与介绍

1、查询语言介绍:

FastDB支持具有类似SQL语法的查询语言。FastDB使用的符号在面向对象编程中比在关系数据库中更受欢迎。表行被视为对象实例,表是这些对象的类。与SQL不同,FastDB面向的是使用对象,而不是SQL元组。因此,每次查询执行的结果都是一个类的一组对象。FastDB查询语言与标准SQL的主要区别在于:

1、 没有几个表和嵌套子查询的联接。查询总是从一个表中返回一组对象。

2、 标准C类型用于原子表列。

3、 除了空引用之外,没有空值。我完全同意C.J.Date对三值逻辑的批评,以及他使用默认值的建议。

4、 结构和数组可以用作记录组件。提供了一个特殊的存在量化器来定位数组中的元素。

5、 可以为表记录(对象)以及记录组件定义无参数用户方法。

6、 应用程序可以定义(只有)一个字符串或数字参数的用户函数。

7、 支持对象之间的引用,包括对反向引用的自动支持。

8、 从后面开始的构造使用引用执行递归记录遍历。

9、 由于查询语言被深度集成到C++类中,因此对语言标识符和关键字都使用了区分大小写的模式。

10、 没有完成整数和浮点类型到字符串表示形式的隐式转换。如果需要这样的转换,就必须明确地进行。

下面以类似BNF的符号表示法规定了FastDB查询语言搜索谓词的语法:

标识符区分大小写,以a-z、a-z、'_'或'$'字符开头,仅包含a-z、a-z、0-9、'_‘或'$‘字符,并且不重复SQL保留字。

保留字列表 
abs and asc between by
current desc escape exists false
first follow from in integer
is length like last lower
match not null or real
start string true upper

也可以使用ANSI标准注释。双连字符后直到行尾的所有字符都将被忽略。

FastDB通过支持位操作来扩展ANSI标准SQL操作。运算符and/or不仅可以应用于布尔操作数,还可以应用于整数类型的操作数。将and/or运算符应用于整数操作数的结果是通过位and/位or运算设置位的整数值。位操作可以用于小集合的有效实现。此外,对于整数和浮点类型,FastDB也支持对幂运算(x^y)的引用。

2、结构

FastDB接受结构作为记录的组成部分。可以使用标准点表示法访问结构的字段如 :company.address.city

结构字段可以按规范的顺序进行索引和使用。结构可以包含其他结构作为其组件;嵌套级别没有限制。

程序员可以定义结构的方法,这些方法可以在查询中使用与正常结构组件相同的语法。这样的方法除了指向它所属对象的指针(C++中的this指针)之外,不应该有任何参数,并且应该返回一个原子值(布尔值、数值、字符串或引用类型)。此外,该方法不应更改对象实例(不可变方法)。如果该方法返回一个字符串,则应该使用new char数组空间 来分配该字符串,因为临时变量将在复制其值后被删除。

因此,用户定义的方法可以用于创建虚拟组件——这些组件不存储在数据库中,而是使用其他组件的值进行计算。例如,FastDB dbDateTime类型仅包含整数时间戳组件和dbDateTime::year()、dbDateTime::month()等方法。。。因此,可以在应用程序中指定诸如“deliveryy.year=1999”之类的查询,其中交付记录字段具有dbDateTime类型。方法是在定义它们的应用程序上下文中执行的,其他应用程序和交互式SQL不可用。

3、数组

FastDB接受具有动态长度的数组作为记录的组成部分。不支持多维数组,但可以定义数组的数组。可以按数组字段的长度对结果集中的记录进行排序。FastDB提供了一组用于处理数组的特殊构造:

通过length()函数可以获得数组中元素的数量。

数组元素可以由[]运算符提取。如果索引表达式超出数组范围,将引发异常。

中的运算符可用于检查数组是否包含由左操作数指定的值。此操作只能用于原子类型的数组:具有布尔值、数值、引用或字符串组件。

数组可以使用update方法更新,该方法创建数组的副本并返回非常量引用。

数组元素的迭代由exists运算符执行。在exists关键字之后指定的变量可以用作exists量化器前面的表达式中数组的索引。此索引变量将遍历所有可能的数组索引值,直到表达式的值变为true或索引超出范围。条件

  exists i: (contract[i].company.location = 'US')

将选择位于“美国”的公司发货的所有详细信息,而查询

 not exists i: (contract[i].company.location = 'US')

将选择从“美国”以外的公司发货的所有详细信息。

允许嵌套的exists子句。使用嵌套的exists量化器相当于使用对应索引变量的嵌套循环。例如查询

    exists i: (contract[i].company.location = 'US')

将选择所有记录,在矩阵字段的元素中包含0,该字段的类型为array或array of integer。此构造等效于以下两个嵌套循环:

 bool result = false;
       for (int column = 0; column < matrix.length(); column++) { 
            for (int row = 0; row < matrix[column].length(); row++) { 
             if (matrix[column][row] == 0) { 
                     result = true;
             break;
                 }
            }
       }

使用索引的顺序至关重要!以下查询执行的结果

  exists row: (exists column: (matrix[column][row] = 0))

将与上一次查询的结果完全不同。在最后一种情况下,在空矩阵的情况下,程序只是由于无限循环而挂起。

4、字符串

FastDB中的所有字符串都有不同的长度,程序员不应该担心字符字段的最大长度的指定。数组可接受的所有操作也适用于字符串。除了它们之外,字符串还有一组自己的操作。首先,可以使用标准关系运算符将字符串相互比较。目前,FastDB只支持ASCII字符集(对应于C中的char类型)和忽略位置设置的逐字节字符串比较。

类似的运算符可用于将字符串与包含特殊通配符“%”和“_”的模式进行匹配。字符“_”与任何单个字符匹配,而字符“%”与零个或多个字符匹配。如果模式中的字符“%”和“_”前面有一个特殊的转义符(在转义关键字之后指定),则可以使用类似运算符的扩展形式和转义关键字将它们作为普通字符处理。

如果您使用USE_REGEX宏重建GigaBASE,那么您可以使用实现标准正则表达式的匹配运算符(基于GNU正则表达式库)。此运算符的第二个操作数指定了要匹配的正则表达式,并且应该是字符串文字。

可以通过in运算符搜索字符串中的子字符串。对于颜色字段包含“蓝色”的所有记录,表达式(颜色为“蓝色”)都将为true。如果搜索字符串的长度大于某个阈值(当前为512),则使用Boyer-Moore子字符串搜索算法,而不是直接的搜索实现。

字符串可以通过+或||运算符连接。最后一个是为了与ANSI SQL标准兼容而添加的。由于FastDB不支持在表达式中隐式转换为字符串类型,因此可以为字符串重新定义运算符+的语义。

Fastdb是一个面向对象的数据库系统,其主要目标是提供高效的、易于使用的数据存储和检索机制。本文将详细介绍Fastdb的特点和使用方法,并解释所有相关的接口。

一、特点

1. 高效性:Fastdb使用预分配对象的方式,减少了向磁盘分配空间的时间开销。它还使用了内存映射I/O技术,有效地减少了基于文件的I/O操作。

2. 安全性:Fastdb使用了事务机制,可以保证对数据的完整性。而且,它提供了可选的数据加密机制,以保护敏感数据。

3. 易于使用:Fastdb提供了面向对象的API,使得程序员可以快速、直接地存储和检索对象。同时,Fastdb提供了具有强大查询能力的索引机制,以便更高效地定位数据。

4. 可扩展性:Fastdb支持多种语言的接口,包括C++、Java、Python等,可以方便地与其他软件集成。

5. 易于部署:Fastdb是一个轻量级的数据库系统,可以很容易地安装和配置。

二、安装

Fastdb针对不同的操作系统提供了不同的安装包,可在其官方网站上下载。安装过程可以根据安装向导进行,也可以使用命令行方式安装。

三、使用

1. 创建数据库

在使用Fastdb之前,我们需要先创建一个数据库。可以通过以下代码创建并打开一个名为“MyDB”、大小为100MB的数据库:

```
  //创建数据库
  db_open("MyDB", 100000000);
  //获取根对象
  dbDatabase* db = dbDatabase::instance();
```

2. 定义对象

Fastdb的对象被定义为类,需要继承于dbObject类。例如,下面定义了一个Person类:

```
  class Person : public dbObject
  {
  public:
      char* name;
      int age;
      dbReference<Person> father;
      dbReference<Person> mother;
      dbArray<dbReference<Person> > children;
  };
```

在这个类中,我们定义了Person的姓名、年龄、父亲、母亲和孩子。dbReference表示一个对象引用,dbArray表示一个对象数组。dbObject类提供了一些常用的函数,例如dbObject::dbObject()、dbObject::~dbObject()、dbObject::clear()等。

3. 存储对象

我们可以使用dbDatabase::addObject()函数将一个新对象添加到数据库中,并返回一个dbReference对象。

```
  //创建一个新的Person对象并存储到数据库中
  Person* p = new Person;
  p->name = "Lucy";
  p->age = 25;
  dbReference<Person> ref = db->addObject(p);
```

4. 查询对象

Fastdb支持多种条件查询方式,可以快速地查找到我们需要的对象。例如,我们可以使用以下代码查找年龄为25岁的人:

```
  //查询年龄为25的人
  dbQuery q;
  q = db->createQuery();
  q.constrain(Person::age, opEqual, 25);
  q.execute();
  while (q.next()) {
      Person* p = q.object();
      cout << p->name << endl;
  }
```

其中,opEqual表示相等条件,还支持opLess、opGreater等。使用dbQuery::execute()函数执行查询,dbQuery::next()函数将游标移到下一个符合要求的对象位置,dbQuery::object()函数返回当前对象的指针。

5. 更新对象

我们可以使用dbDatabase::updateObject()函数更新已经存在的对象。例如,我们可以修改25岁的Lucy的名字:

```
  //修改Lucy的名字
  q = db->createQuery();
  q.constrain(Person::name, opEqual, "Lucy");
  q.constrain(Person::age, opEqual, 25);
  q.execute();
  while (q.next()) {
      Person* p = q.object();
      p->name = "Lucy Li";
      db->updateObject(p);
  }
```

6. 删除对象

我们可以使用dbDatabase::deleteObject()函数删除已经存在的对象。例如,我们可以删除所有年龄大于30岁的人:

```
  //删除年龄大于30的人
  q = db->createQuery();
  q.constrain(Person::age, opGreater, 30);
  q.execute();
  while (q.next()) {
      Person* p = q.object();
      db->deleteObject(p);
  }
```

四、接口解释

dbDatabase类

1. dbDatabase()

函数说明:构造函数,创建一个数据库对象。

2. static dbDatabase* instance()

函数说明:获取数据库的全局实例。

3. void open(const char* name, int size)

参数说明:name-数据库名称,size-数据库大小(字节)。

函数说明:打开一个数据库文件,并将它设置为当前数据库。

4. void close()

函数说明:关闭数据库文件。

5. dbReference<T> addObject(T* obj)

参数说明:obj-要添加的对象。

函数说明:将一个新对象添加到数据库末尾,并返回一个引用。

6. void updateObject(T* obj)

参数说明:obj-要更新的对象。

函数说明:将一个已经存在的对象更新到数据库中。

7. void deleteObject(T* obj)

参数说明:obj-要删除的对象。

函数说明:从数据库中删除一个已经存在的对象。

8. int commit()

函数说明:提交所有的事务。

9. void rollback()

函数说明:回滚所有的事务。

10. dbQuery createQuery()

函数说明:创建一个查询对象。

11. template <class T> dbReference<T> getReference(T* obj)

参数说明:obj-对象。

函数说明:获取一个对象的引用。

dbQuery类

1. dbQuery(dbDatabase* db)

参数说明:db-数据库对象。

函数说明:构造函数。

2. ~dbQuery()

函数说明:析构函数。

3. void close()

函数说明:关闭查询对象。

4. void reset()

函数说明:重置查询条件。

5. void constrain(dbFieldDescriptor* fd, dbComparisonOperator op, const void* value)

参数说明:fd-一个字段描述器,op-比较操作符,value-比较值。

函数说明:增加一个查询条件。

6. void orderBy(dbFieldDescriptor* fd, bool ascending=true)

参数说明:fd-一个字段描述器,ascending-是否升序排列。

函数说明:指定排序方式。

7. void select(const char* fieldName)

参数说明:fieldName-要返回的字段名称。

函数说明:指定要返回的字段。

8. bool execute()

函数说明:执行查询。

9. bool next()

函数说明:移动游标到下一个结果。

10. dbReference<T> object()

函数说明:返回当前游标所指向的对象引用。

dbFieldDescriptor类

1. dbFieldDescriptor(const char* name, int type, size_t length, int flags)

参数说明:name-字段名称,type-字段类型(int、float、double、char[]等),length-字段长度(对于char[]类型的字段有用),flags-字段属性(比如索引)。

函数说明:构造函数。

dbReference类

1. bool operator== (const dbReference& r)

参数说明:r-一个引用。

函数说明:判断两个引用是否相等。

2. bool operator!= (const dbReference& r)

参数说明:r-一个引用。

函数说明:判断两个引用是否不相等。

3. operator const T* ()

函数说明:将引用转换为指向T类型的指针。

dbArray类

1. dbArray<T>()

函数说明:构造函数。

2. void resize(int n, bool save=true)

参数说明:n-新数组大小,save-是否保留旧数据。

函数说明:重新调整数组大小。

3. void clear()

函数说明:清空数组内容。

4. void add(const T& item)

参数说明:item-要添加的项。

函数说明:将一个项添加到数组末尾。

5. T& operator[](int i) const

参数说明:i-数组下标。

函数说明:获取指定下标的项。

6. int length()

函数说明:获取数组长度。

以上就是Fastdb的详细介绍和所有接口的解释,希望对大家有用。

相关推荐

  1. <span style='color:red;'>FastDFS</span>

    FastDFS

    2024-03-10 06:54:09      54 阅读
  2. 浅析数据汇总

    2024-03-10 06:54:09       52 阅读
  3. Linux内核中的链表浅析

    2024-03-10 06:54:09       31 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-10 06:54:09       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-10 06:54:09       106 阅读
  3. 在Django里面运行非项目文件

    2024-03-10 06:54:09       87 阅读
  4. Python语言-面向对象

    2024-03-10 06:54:09       96 阅读

热门阅读

  1. 区块链web3智能合约Solidity学习资源整理

    2024-03-10 06:54:09       45 阅读
  2. 【MySQL 系列】在 Ubuntu 上安装 MySQL

    2024-03-10 06:54:09       49 阅读
  3. bash 给表格加列名

    2024-03-10 06:54:09       40 阅读
  4. C++ 友元

    2024-03-10 06:54:09       44 阅读
  5. 我和我的DBA之路

    2024-03-10 06:54:09       43 阅读
  6. 2024年FPGA可以进吗

    2024-03-10 06:54:09       38 阅读
  7. 物联网与边缘计算的结合

    2024-03-10 06:54:09       39 阅读
  8. openssl3.2 - exp - PEM <==> DER

    2024-03-10 06:54:09       51 阅读