1.3.2 数据模型

优质
小牛编辑
136浏览
2023-12-01

表模式

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

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

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

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

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

    • 局部二级索引组(可选,需要先设置实体组键)用以提升对某些属性的读性能。二级索引和实体组键不能是相同属性
  • 主键(Primary Key)(必选) 主键也可以包含一个或多个属性,实体主键+主键唯一确定一条记录

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

表示例

cityprovincepm25scoretimestamp
LianyungangJiangsu35726.01537264064

对于这张示例表,可以有以下三种定义方式:

例1city可以单独作为主键,而provincepm25scoretimestamp作为其余属性

例2city+province作为主键,pm25scoretimestamp作为其余属性

例3city作为主键,score作为实体组键,timestamp作为局部二级索引

属性支持如下数据类型:

数据类型Java SDKPHP SDKPython SDKGo SDKc++ SDKnode.js SDK备注
BOOLbooleanbooleanboolboolboolboolean-
INT8byteintegerintint8int8_tnumber-
INT16shortintegerintint16int16_tnumber-
INT32intintegerintint32int32_tnumber-
INT64longintegerlongint64int64_tnumber-
FLOATfloat不支持floatfloat32不支持number-
DOUBLEdoubledoublefloatfloat64doublenumber-
STRINGStringstringstrstringstringstring不能包含'\0'
BINARYbyte[]stringstring[]bytestringstring-
RAWBINARYbyte[]不支持不支持[]byte不支持不支持不能作为实体组键,主键和二级索引属性
集合类型Listarraylistslicevectorarray支持二级索引

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

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

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

      这几种索引会造成不同的额外配额消耗,用户需要按照实际应用场景选用合适的索引类型

开发者可以根据数据的读取模式,选择是否支持实体组键,以及是否定义二级索引。
二索引类别适用场景解释
LAZY写多读少适合写入较多,读取较少且对延迟不敏感的情况
EAGER写少读多与投影配合使用,适合读取相对频繁或者对读延迟比较敏感的场合
IMMUTABLE适合只读数据即写入后数据不再修改

目前不支持动态修改表的实体组键(包括哈希分布选项),主键,除索引类型外的其 他二级索引选项),以及属性的数据类型和编码方式

名称实体组键主键索引类型表属性数据类型编码方式
动态修改不支持不支持仅允许由Immutable->Eager不支持不支持不支持
注意:建表时需要慎重选择。表的普通属性可以增删,但数据访问会有短暂停服(平均在2-3秒),建议在业务低峰期操作。

二级索引的类型可以修改,但仅允许Immutable改为Eager,适合当表中数据由不可更新改为可写的情况。 一种常见的场景是:

建表初期导入已有数据,此时数据是只读的,不会存在更新的情况(需要开发者自己保证), 此时索引定义为Immutable,可以节约读配额,数据导入完成后开始线上服务之前,将索引改为Eager模式。

哈希分布

对于实体组键,可以定义是否进行哈希分布,开启此选项后, 会添加取值范围为[0,255]的哈希值,从而实现负载均衡的效果,可用于消除请求热点,建议开启。

需要注意, 打开此选项后,表中的数据将不再保证全局有序。一般情况下,没有特殊原因,强烈建议设置实体组键并开启哈希

设计表的Schema以及估算请求量时,应保证每个实体组上的单位时间消耗的读写配额峰值尽可能的小,原则上不应不超过1000/秒,否则将不保整个表的读写请求配额。实体组的数量的多少不影响性能,所以在满足业务查功能前提下,应该尽可能降低每个实体组上的读写配额,避免读写热点,尤其避免同时大量读写一个或少数几个实体组中的记录

注意: 当实体组键开启哈希分布时,主键需要包含至少一个属性,如果schema中没有可以作为主键的属性,建议在主键中 使用一个默认的占位属性(例如,如果一个表只有一个userId作为实体组键属性,那么可以添加一个额外的recordId 属性作为主键,取值为常数0,表示某个用户下的第1条记录)。

升序与降序

对于实体组键,主键以及二级索引的属性的编码(KeySpec),可以通过asc选择决定是否是升序还是降序(例如, 整型降序编码时,其排序为..., 2, 1, 0, -1, ...与正序相反)。

正序扫描和逆序扫描

对于扫描(Scan)操作,可以通过通过设置 reverse选项进行正序和逆序扫描,但是正序扫描效率高于逆序扫描,所以定义表结构的时候,需要根据关键路径 上的查询模式来决定编码顺序,尽量保证关键路径是正序扫描。

记录行的物理组织格式

  • 未设置实体组键的表物理组织

      主记录行1
      主记录行2
      ...
      主记录行n
    
  • 设置实体组键的表物理组织

      主记录行1
      二级索引行1
      主记录行2
      二级索引行2
      ...
      主记录行n
      二级索引行n
    
  • 主记录(主键)行的组织形式为
    [实体组前缀] [主键属性1] ... [主键属性m]:{表属性1, ..., 表属性p}

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

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

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

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

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

二级索引行在物理存储时同样按照以上定义的顺序进行存储。

  • 投影属性

    1、投影属性是主记录行属性的副本,与主数据行总是保证一致,且仅当eager索引才可以定义投影属性。 2、投影属性以空间换取时间,在仅查找二级索引的情况下可以快速读取既定属性的值

一致性

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

事务性

  • 行级别的事务保证

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

  • 实体组内的事务保证

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

  • 自增操作支持

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

  • 条件修改

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