Nee*_*asu 7 database data-modeling key-value-store leveldb rocksdb
我是商店的新手key-value。我的目标是使用嵌入式键值存储来保持持久数据模型。如果使用传统的 RDBMS 设计,数据模型将包含很少的相关表。我正在查看一篇关于为键值存储建模表的中等文章。尽管本文使用 Level DB 和 Java,但我计划在我的工作中使用 Level DBRocksDB或FASTERC++。
它使用一种方案,其中每行的每个属性都使用一个键,如下例所示。
$table_name:$primary_key_value:$attribute_name = $value
当用户代码确切地知道要获取哪个键时,上面的内容对于点查找来说是很好的。但也有一些场景,比如搜索具有相同电子邮件地址的用户,或者搜索超过一定年龄的用户,或者搜索某一特定性别的用户。在搜索场景中,文章对所有键执行线性扫描。在每次迭代中,它都会检查键的模式,并在找到具有匹配模式的键后应用业务逻辑(检查匹配的值)。
看来,这种类型的搜索效率很低,在最坏的情况下需要遍历整个商店。为了解决这个问题,需要一个反向查找表。我的问题是
如何建模反向查找表?这是某种轮子的重新发明吗?有什么替代方法吗?
很容易想到的一个解决方案是separate ?为每个可索引属性建立一个存储,如下所示。
$table_name:$attribute_name:$value_1 = $primary_key_value 
采用这种方法,迫在眉睫的问题是
如何处理这个反向查找表中的冲突?因为多个
$primary_keys 可能与同一个值相关联。
作为直接的解决方案,可以不存储单个值,而是array存储多个主键,如下所示。
$table_name:$attribute_name:$value_1 = [$primary_key_value_1, ... , $primary_key_value_N]
但是这种类型的建模需要用户代码从字符串解析数组,并在多次操作后再次将其序列化为字符串(假设底层键值存储不知道数组值)。
将多个键存储为数组值是否有效?或者存在一些供应商提供的有效方法?
假设类似字符串化的数组设计有效,每个可索引属性都必须有这样的索引。因此,这提供了对索引什么和不索引什么的细粒度控制。想到的下一个设计决策是这些索引将存储在哪里?
索引应该存储在单独的存储/文件中吗?或者在实际数据所属的同一存储/文件中?每个房产是否应该有不同的商店?
对于这个问题,我没有任何线索,因为这两种方法都需要或多或少相同数量的 I/O。然而,如果数据文件较大,则磁盘上的内容较多,内存上的内容较少(因此 I/O 较多),而对于多个文件,内存上的内容较多,因此页面错误较少。根据特定键值存储的架构,这种假设可能是完全错误的。同时,文件太多会成为管理复杂文件结构的问题。此外,维护索引需要插入、更新和删除操作的事务。拥有多个文件会导致多个树中的单个更新,而拥有单个文件会导致单个树中的多个更新。
交易是否更具体地支持涉及多个存储/文件的交易?
不仅是索引,还有表的一些元信息也需要与表数据一起保存。要生成新的主键(自动递增),需要先了解最后生成的行号或最后一个主键,因为类似 a 的东西COUNT(*)不起作用。另外,由于未对所有键建立索引,因此该meta信息可包括对哪些属性建立索引以及对哪些属性未建立索引。
如何存储每个表的元信息?
同样的一组问题也出现在元表中。例如元应该是一个单独的存储/文件吗?此外,我们注意到并非所有属性都被索引,我们甚至可能决定将每一行作为 JSON 编码值存储在数据存储中,并将其与索引存储一起保存。底层键值存储供应商会将该 JSON 视为字符串值,如下所示。
$table_name:data:$primary_key_value = {$attr_1_name: $attr_1_value, ..., $attr_N_name: $attr_N_value}
...
$table_name:index:$attribute_name = [$primary1, ..., $primaryN]
然而,通过指向主键的索引仍然可以进行反向查找。
使用 JSON 编码值而不是将所有属性存储为单独的键有什么缺点吗?
到目前为止,除了强制用户使用 JSON 编码以及用于 JSON 编码/解码的一些堆分配之外,我找不到使用此方法的任何缺点。
上述问题并不特定于任何特定应用。这些问题非常普遍,足以与使用 store 的所有开发相关联key-value。因此,有必要了解是否有轮子的重新发明。
问题中提到的所有问题是否有事实上的标准解决方案?解决方案与问题中所述的解决方案是否不同?
如何建模反向查找表?这是某种轮子的重新发明吗?有什么替代方法吗?
如何处理这个反向查找表中的冲突?因为多个 $primary_keys 可能与同一个值关联。
您可以使用 JSON(或其他方式)序列化 pks。这种方法的问题是当 pks 变得非常大时(这可能是也可能不是)。
将多个键存储为数组值是否有效?或者存在一些供应商提供的有效方法?
有了 RocksDB,你就没有什么可以让它变得“更容易”了。
您没有提到以下方法:
$table_name:$attribute_name:$value_1:$primary_key_value_1 = ""
$table_name:$attribute_name:$value_1:$primary_key_value_2 = ""
...
$table_name:$attribute_name:$value_1:$primary_key_value_n = ""
值为空的地方。索引pk是键的一部分。
索引应该存储在单独的存储/文件中吗?或者在实际数据所属的同一存储/文件中?每个房产是否应该有不同的商店?
这取决于键值存储。使用rocksdb,如果您需要事务,则必须坚持使用一个数据库文件。
交易是否更具体地支持涉及多个存储/文件的交易?
只有 Oracle Berkeley DB 和 WiredTiger 支持该功能。
如何存储每个表的元信息?
元数据可以位于数据库或代码中。
使用 JSON 编码值而不是将所有属性存储为单独的键有什么缺点吗?
是的,就像我上面说的,如果将所有 pk 编码为单个值,当 pk 数量很大时,可能会导致下游出现问题。例如,您需要读取整个列表才能进行分页。
问题中提到的所有问题是否有事实上的标准解决方案?解决方案与问题中所述的解决方案是否不同?
总结一下:
| 归档时间: | 
 | 
| 查看次数: | 1724 次 | 
| 最近记录: |