大对象

概念

大对象LOB (Large Object) 的功能是为了突破 SequoiaDB 巨杉数据库的单条记录最大长度为 16MB 的限制,为用户写入和读取更大型记录提供便利。对于文档、图片、音频和视频等非结构化的数据,用户可以使用 LOB 存储。LOB 存放在集合中,每一个 LOB 都需要一个 OID 来唯一标示。LOB 的内容只存放在一个集合中,当集合被删除时,其拥有的 LOB 将自动删除。

存放 LOB 的集合应该满足如下要求:

  • 当集合是普通集合,集合只存在某一个数据组中。此时,LOB 的最大容量为集合能使用的最大文件空间。
  • 当集合是哈希分区集合,LOB 对该哈希分区集合的 ShardingKey 没有要求。一般情况下,用户在创建哈希分区集合来存放 LOB 时,可以使用 "_id" 键作为 ShardingKey。当集合为哈希分区集合时,集合存在一个或者多个数据组中。在这种情况下,LOB 最大的容量由哈希分区集合使用的数据组的数据决定。

存储结构

LOB 以集合为单位进行存储,因此它保持集合空间和集合的逻辑结构。在磁盘的数据存储中,对应的集合空间会增加 2 个文件:

[CollectionSpace].1.lobm
[CollectionSpace].1.lobd

LOBM 文件和 LOBD 文件一一对应,LOBM 为元数据文件,用于 LOB 数据页的分配、查找和管理;LOBD 为 LOB 的数据存储文件,存储真实的数据。

LOBD 在存储数据时,以数据页为最小单位。数据页大小最小为 4KB,最大为 512KB,默认为 256KB。在 LOBD 上存放数据时,若 LOB 总大小小于 1 个数据页的大小,该 LOB 也会独占整个数据页,哪怕该 LOB 大小只有 1 Byte。所以,当存储的 LOB 总大小较小时,用户应该选择适当的数据页大小来存储 LOB 的内容,以减少空间浪费。关于 LOB 的数据页大小的选择,可参考 Sdb.ceateCS() 的 LobPageSize 参数的介绍。

LOBM 和 LOBD 的存储结构如图 1 所示。

LOB 存储文件结构图

功能介绍

目前,LOB 支持以下功能(需要改成表格呈现):

  • 顺序读写和随机读写
  • 打开读操作和打开写操作
  • 并发读和并发写

在对 LOB 进行操作时,应该注意:

  • 在创建 LOB 时,LOB 对象不可读,也不可删除。
  • 在打开读 LOB 时,LOB 对象不可写,也不可删除,可以并发读。
  • 在打开写 LOB 时,LOB 对象不可读,也不可删除,可以并发写。并发写时需要按写入的数据段加锁并 seek 到加锁的数据段后写入数据。并发锁定的数据段不能重叠。当某数据段被锁定后,其上面的数据将可被覆盖写入。关于 LOB 的 seek, lock 和 lockAandSeek 操作,可查看各驱动 LOB 相关 API 的说明。
  • 在删除 LOB 时,LOB 对象不可读写。

操作说明

下表以在 Sdb Shell 上操作 LOB 来介绍 LOB 相关 API 的使用。

LOB 操作 参见 说明 相关 API
创建 SdbCollection.putLob() 向集合创建一个 LOB。 SdbCollection::openLob() // 以创建的方式打开
SdbLob::write()
SdbLob::close()
读取 SdbCollection.getLob() 从集合读取某个 LOB 记录。 SdbCollection::openLob() // 以只读的方式打开
SdbLob::read()
SdbLob::close()
删除 SdbCollection.deleteLob() 删除集合某个 LOB 对象。 SdbCollection::removeLob()
列表 SdbCollection.listLobs() 列出集合所有 LOB 对象。 SdbCollection::listLobs()

Note:

  • SDB Shell 使用 CPP 驱动连接数据库,上表相关 API 是 CPP LOB API 的情况。其他驱动的 LOB API 拥有类似的接口。详情请参考相关的驱动。
  • 关于 LOB 的更多 API 说明,请参考各驱动 LOB API 的说明。

示例

1.在 Sdb Shell 中将本地视频文件 video_2019_02_26_1.avi 上传至集合 sample.video 中:

  > db.sample.video.putLob( '/opt/video_2019_02_26_1.avi' )
  5435e7b69487faa663000897

2.在 Sdb Shell 中查看集合 sample.video 中所有 LOB 及其对应的 OID:

  > db.sample.video.listLobs()
  {
    "Size": 76602,
    "Oid": {
      "$oid": "5435e7b69487faa663000897"
    },
    "CreateTime": {
      "$timestamp": "2019-02-26-12.51.43.628000"
    },
    "ModificationTime": {
      "$timestamp": "2019-02-26-12.51.45.523000"
    },
    "Available": true
  }

3.在 Sdb Shell 中将集合 sample.video 中的 OID 为 435e7b69487faa663000897 的LOB 下载到本地文件 video_2019_02_26_1_bak.avi 中:

  > db.sample.video.getLob( '5435e7b69487faa663000897', '/opt/video_2019_02_26_1_bak.avi' )

4.在 SDB Shell 中将集合 sample.video 中的 OID 为 5435e7b69487faa663000897 的 LOB 记录删除:

  > db.sample.video.deleteLob( '5435e7b69487faa663000897' )
回到顶部