数据模型


表模式

SDS 数据模型概念包括记录属性

在SDS中表是记录的集合,记录是属性的集合。

在SDS中表具有预定义的架构,属于强schema模型,即用户可设定表名,表的实体组键,主键,其余属性的名称和数据类型

  • 表名(必选) 在每个用户下表名唯一

  • 实体组键(可选) 实体组键可以是一个或多个属性,实体组键用于支持局部二级索引与及哈希分布

  • 主键(必选) 主键也可以包含一个或多个属性,实体主键+主键唯一确定一条记录

  • 其余属性(可选) 记录中每个属性都是一个名称/值对,一个属性可以只有一个值,也可以是具有多个值的集合

属性支持如下数据类型:

数据类型 Java SDK PHP SDK Python SDK Go SDK c++ SDK node.js SDK 备注
BOOL boolean boolean bool bool bool boolean -
INT8 byte integer int int8 int8_t number -
INT16 short integer int int16 int16_t number -
INT32 int integer int int32 int32_t number -
INT64 long integer long int64 int64_t number -
FLOAT float 不支持 float float32 不支持 number -
DOUBLE double double float float64 double number -
STRING String string str string string string 不能包含'\0'
BINARY byte[] string string []byte string string -
RAWBINARY byte[] 不支持 不支持 []byte 不支持 不支持 不能作为实体组键,主键和二级索引属性
集合类型 List array list slice vector array 支持二级索引

表的数据在物理组织上支持两种索引结构:

  • 主键 索引(Primary Key index) - 必选,由一到多个表属性组成
    • 所有其余属性按照实体组键(若有)+主键顺序存储,写入时必须指定实体组键(若有)和主键,每条数据消耗1个单位写配额, 读取时,每条记录消耗1个单位读配额
  • 局部二级索引 (Local Secondary Index) - 可选,使用局部二级索引必须要定义实体组键,由一个到多个表属性组成。索引分为LazyEagerImmutable三种类别

    • Lazy索引 - 此类型的索引不支持投影属性和唯一索引。
    • Eager索引 - 此类型的索引可以支持唯一索引(Unique Index),并且可以定义一组属性作为 投影(Projection),与索引存储在一起(可视为主记录中对应属性的一份拷贝,并且属性值保持强 一致)。
    • Immutable索引 - 此类型的索引适合只读数据,即写入后数据不会再修改(需要用户自己来保证)。 此类型索引支持投影,但不支持唯一索引。

      这几种索引会造成不同的额外配额消耗,用户需要按照实际应用场景选用合适的索引类型 Lazy索引适合写多读少,修改,删除少的场景,Eager索引适合写少读多,Immutable索引适合只读数据,即写入后数据不再修改

另外,在表的定义中,可以将一到多个表属性定义为 实体组键(Entity Group Key),在物理组织上, 实体组键是记录主键和二级索引的前缀。对于实体组键,可以定义是否进行哈希分布,开启此选项后, 会添加取值范围为256的哈希值,从而实现负载均衡的效果,可用于消除请求热点,建议开启。需要注意, 打开此选项后,表中的数据将不再保证全局有序。一般情况下,没有特殊原因,强烈建议设置实体组键并开启哈希 (设计表的Schema以及估算请求量时,应保证每个实体组上的单位时间消耗的读写配额峰值尽可能的小,原则上 不应不超过1000/秒,否则将不保整个表的读写请求配额。实体组的数量的多少不影响性能,所以在满足业务查询 功能前提下,应该尽可能降低每个实体组上的读写配额,避免读写热点,尤其避免同时大量读写一个或少数几个 实体组中的记录)。 当实体组键开启哈希分布时,主键需要包含至少一个属性,如果schema中没有可以作为主键的属性,建议在主键中 使用一个默认的占位属性(例如,如果一个表只有一个userId作为实体组键属性,那么可以添加一个额外的recordId 属性作为主键,取值为常数0,表示某个用户下的第1条记录)。

对于实体组键,主键以及二级索引的属性的编码(KeySpec),可以通过asc选择决定是否是升序还是降序(例如, 整型降序编码时,其排序为..., 2, 1, 0, -1, ...与正序相反)。对于扫描(Scan)操作,可以通过通过设置 reverse选项进行正序和逆序扫描,但是正序扫描效率高于逆序扫描,所以定义表结构的时候,需要根据关键路径 上的查询模式来决定编码顺序,尽量保证关键路径是正序扫描。

主记录(主键)行的组织形式为:

    [实体组前缀] [主键属性1] ... [主键属性m]:
    {表属性1, ..., 表属性p}

物理存储时,会按照以上定义的顺序进行存储,即先按实体组前缀,和主键属性1到m的顺序,再根据属性定义的编码方式(asc/desc),对实体组键的属性和主键属性编码成rowkey,进行排序存储

其中实体组前缀是可选的,仅当表定义了实体组键时和二级索引时,二级索引行的组织形式为:

    [实体组前缀] [索引id] [二级索引属性1] ... [二级索引属性n] [主键属性1] ... [主键属性m]:
    {投影属性1, ..., 投影属性q}

前面已经提到,投影属性为主记录行的副本,与主数据行总是保证一致,且仅当eager索引才可以定义投影属性。

同样,物理存储时,也会按照以上定义的顺序进行排序存储

其中实体组键前缀的组成形式为:

    [实体组哈希值] [实体组键属性1] ... [实体组键属性k]

开发者可以根据数据的读取模式,选择是否支持实体组键,以及是否定义二级索引。同时,二级索引需要根据 读写的比例选择类型,例如 Lazy索引 适合写入较多,读取较少且对延迟不敏感的情况。Eager索引 与 投影配合使用,适合读取相对频繁或者对读延迟比较敏感的场合。而只读数据则适合采用Immutable索引。 需要注意的是,目前不支持动态修改表的实体组键(包括哈希分布选项),主键,除索引类型外的其 他二级索引选项),以及属性的数据类型和编码方式,建表时需要慎重选择。表的普通属性可以增删, 但数据访问会有短暂停服(平均在2-3秒),建议在业务低峰期操作。 二级索引的类型可以修改,但仅允许Immutable改为Eager,适合当表中数据由不可更新改为可写的情况。 一种常见的场景是,建表初期导入已有数据,此时数据是只读的,不会存在更新的情况(需要开发者自己保证), 此时索引定义为Immutable,可以节约读配额,数据导入完成后开始线上服务之前,将索引改为Eager模式。

一致性

SDS存储是强一致的模型,即后续发生的读总能读到以前写入的数据。数据存储三备份,并且会异步的同步到备集群,备集群目前只提供只读功能,用于离线分析。

事务性

  • 行级别的事务保证

    对于同一次put(非batch)的记录数 据,能够保证原子性,例如,两个并发的put分别写入同一行的两个属性pq: (p1, q1)和(p2, q2), 最终结果不会出现(p1, q2)或者(p2, q1)的情况。

  • 实体组内的事务保证

    属于同一事务组内的记录行,可以支持batch的原子性,可以在建表的时候进行配置是否开启,如果需要定义二级索引,则必须开启batch原子性。同一事务组内可以支持局部二级索引,并且索引跟主记录之间是强一致的。

  • 自增操作支持

    目前支持在整型数据类型上的自增操作

  • 条件修改

    SDS支持条件修改(putdelete),这样可以在应用层实现自己的同步逻辑(比如锁)。

results matching ""

    No results matching ""