在写入Riak的对象中包含辅助索引(2i)对性能有什么影响?
让我们考虑两种场景,这两种场景都有大量对象在一个桶中。每个对象都有一个辅助索引,我们称其为example_bin (但也可以是整数索引):
example_bin的几乎每个值都是不同的值。对索引的一个特定值的查询只返回一个或几个对象。这样的索引可以是电子邮件地址或注册时间(作为unix时间戳)。example_int索引只有几个可能的值。因此,对特定索引值的查询返回大量对象。这样的索引可以代表用户类别,如“管理员”或“客户”。更新这些对象时对性能的影响是什么?我知道每次更新对象时都需要检查索引。以上两个示例中的任何一个都可以包含里亚克耗时或资源消耗的任务吗?
发布于 2015-02-09 21:05:05
使用LevelDB作为后端时更新Riak中的对象的性能影响不应受每个索引中有多少项的影响。但是,它可能会受到以下因素的影响:每个分区中存储的数据总数,以及自上次更新键以来写入的数据数量,以及为该单个对象指定了多少不同的索引项。
LevelDB如何存储数据
当一个值被写入LevelDB时,它将被添加到顶层的.log文件中。当.log文件达到一定大小时(我认为是1Mb,请不要记住该大小是否是可配置的),该文件将被切断并启动一个新的文件。这些文件没有排序。当顶层(0级)有几个文件时,就会触发压缩。压缩将组合一个或多个顶级文件,对其中包含的键进行排序,并将这些排序后的列表与级别1中的适当.sst文件合并。为每个排序级别创建一个清单文件,指示每个.sst文件中存储的键的范围。对于较低级别来说,这一过程也是必要的,每个级别都能够存储上一个级别的大约10倍的数据量。
当为已经存在的键写入一个新值时,只需将其写入顶层,掩盖以前在较低级别中写入的任何值。当正常压缩将新值向下移动到较低级别时,将替换以前的值。
这对阅读有何影响
当请求密钥时,LevelDB从0级开始,检查那里的每个文件是否包含密钥。如果没有,则移至第1级,并检查清单所指示的包含密钥的文件。在找到键或达到最低级别之前,将依次对较低级别重复此操作。因此,返回键的最新写入值。随着每个LevelDB后端存储的数据量的增加,所使用的级别数、必须搜索的文件数量以及读取最老数据的时间都会增加。
如何在LevelDB后端实现索引
在LevelDB后端存储值时,后端使用的原始键是{o,Bucket,Key}的文本编码。如果在对象中指定了任何索引项,则为每个索引存储一个额外的键,即{i,Bucket,IndexName,IndexValue,Key}的文本编码。
为了在更新值时删除任何过时的索引项,必须在每个PUT或DELETE之前执行GET,将前一个对象的索引规范与存储的对象的索引规范相比较,删除任何过时的{i,...}键并添加任何新的索引项。
索引查询
因为LevelDB以排序的方式存储数据,所以索引查询从键{i,Bucket,IndexName,FirstValue,<<>>}开始通过{i,Bucket,IndexName,LastValue,<<255,255,255,255>>}实现(二进制<<255,...是一个理论值,指示排序顺序中的最后一个可能的键)。参考每个排序级别中的清单,因此只需要打开包含正在折叠的范围的一部分的数据文件。
摘要
example_bin的几乎每个值都是不同的值。对索引的一个特定值的查询只返回一个或几个对象。这样的索引可以是电子邮件地址或注册时间(作为unix时间戳)。
查询所需的索引项和单个值很可能完全落在每个排序级别中的单个文件中,因此该查询将需要打开和搜索级别0中的所有文件,而在每个较低级别上则需要有一个文件。目前的级别数取决于存储的数据量,将是最大的决定因素。
example_int索引只有几个可能的值。因此,对特定索引值的查询返回大量对象。这样的索引可以代表用户类别,如“管理员”或“客户”。
查询单个值的索引条目范围更大,使得每个排序级别需要查询多个文件的可能性更大。由于折叠中包含了更多的索引条目,并且可能需要打开更多的文件,此查询将比上一次查询要花费更长的时间。
更新这些对象时对性能的影响是什么?我知道每次更新对象时都需要检查索引。以上两个示例中的任何一个都可以包含里亚克耗时或资源消耗的任务吗?
这里所需的时间将取决于检索任何旧对象所需的时间,以及索引条目的更改数量。在此过程中,从来没有将整个索引作为一个整体来考虑,只有上一个对象上的条目和新对象上的条目。因此,性能不会受到任何索引中的条目数的影响,而是受该对象有或有条目的索引数的影响。
https://stackoverflow.com/questions/28411145
复制相似问题