我是key-value
商店的新手。我的目标是使用嵌入式键值存储来保留持久数据模型。如果使用常规RDBMS设计,则数据模型包含很少的相关表。我正在检查有关为键值存储表建模的medium article。尽管本文将Level DB与Java结合使用,但我仍计划在C ++中将RocksDB
或FASTER
与C ++一起使用。
[它使用一种方案,其中每一行的每个属性都使用一个键,如下面的示例。
$table_name:$primary_key_value:$attribute_name = $value
当用户代码确切知道要获取哪个键时,以上对于点查找很好。但是,有些情况下,例如搜索具有相同电子邮件地址的用户,搜索特定年龄以上的用户或搜索一种特定性别的用户。在搜索方案中,文章将对所有键进行线性扫描。在每次迭代中,一旦找到具有匹配模式的键,它就会检查键的模式并应用业务逻辑(检查匹配值)。
似乎,这种类型的搜索效率低下,在最坏的情况下,它需要遍历整个商店。为了解决这个问题,需要一个反向查询表。我的问题是
如何为反向查询表建模?这是车轮的重塑吗?还有其他方法吗?
一个容易想到的解决方案是为每个可索引属性设置separate ?
存储,如下所示。
$table_name:$attribute_name:$value_1 = $primary_key_value
使用这种方法,直接的问题是
如何处理此反向查询表中的冲突?因为多个
$primary_key
可能与同一标签相关联。
作为一种立即解决方案,可以存储多个主键的array
,而不是存储单个值,如下所示。
$table_name:$attribute_name:$value_1 = [$primary_key_value_1, ... , $primary_key_value_N]
但是这种类型的建模需要用户代码从字符串中解析数组,并在多次操作后再次将其序列化为字符串(假定基础键值存储不了解数组值)。
将多个键存储为数组值是否有效?还是存在一些提供有效方法的供应商?
假定像设计那样的字符串化数组起作用,每个可索引属性必须有这样的索引。因此,这为要索引的内容和不索引的内容提供了细粒度的控制。接下来要考虑的设计决策是这些索引将存储在哪里?
索引应存储在单独的存储/文件中吗?还是实际数据属于同一存储/文件?每个属性应该有不同的商店吗?
对于这个问题,我没有任何线索,因为这两种方法都需要或多或少相同数量的I / O。但是,具有大数据文件将在磁盘上存储更多内容,而在内存中减少存储内容(因此增加I / O),而对于多个文件,将在内存中存储更多内容,从而减少页面错误。根据特定键值存储的体系结构,这种假设可能是完全错误的。同时,文件过多会成为管理复杂文件结构的问题。同样,维护索引需要事务进行插入,更新和删除操作。具有多个文件导致在多个树中进行单个更新,而具有单个文件导致在单个树中进行多个更新。
更具体地说,是否涉及多个存储/文件的交易?
不仅索引,表的一些元信息也需要与表数据一起保存。要生成新的主键(自动递增),需要先了解最后生成的行号或生成的主键,因为类似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编码/解码进行一些堆分配外,我无法使用此方法找到任何缺点。
上述问题并非特定于任何特定应用。这些问题足够通用,可以与使用key-value
存储的所有开发相关联。因此,有必要知道是否对车轮进行了重新发明。
问题中提到的所有问题都有事实上的标准解决方案吗?解决方案是否与问题中所述的解决方案不同?
如何为反向查询表建模?这是车轮的重塑吗?还有其他方法吗?
如何处理此反向查询表中的冲突?因为多个$ primary_keys可能与同一个vale相关联。
您可以使用JSON(或其他方式)序列化pk。这种方法的问题是,当pk变得非常大时(可能是也可能不是东西)。
将多个键存储为数组值是否有效?还是存在一些提供有效方法的供应商?
使用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,如果需要事务,则必须坚持一个db文件。
更具体地说,是否涉及多个存储/文件的交易?
[仅Oracle Berkeley DB和WiredTiger支持该功能。
如何存储每个表的元信息?
元数据可以在数据库或代码中。
使用JSON编码值而不是将所有属性存储为单独的键是否有任何弊端?
是的,就像我上面说的那样,如果您将所有pk编码为一个值,那么当pk数量很大时,可能会导致下游问题。例如,您需要阅读整个列表才能进行分页。
问题中提到的所有问题都有事实上的标准解决方案吗?解决方案是否与问题中所述的解决方案不同?
总结: