考虑一组名为 Library 的数据,其中包含一组 Books ,每本书都包含一组 Pages 。
假设您使用Riak存储此数据,您需要以两种可能的方式访问数据: - 查询特定页面(具有唯一ID) - 查询特定书籍中的所有页面(具有唯一名称)
此外,您需要能够轻松更新和删除特定图书的网页。
在Riak中实现这一目标的最佳途径是什么?
显然Riak Search会做到这一点,但对我想做的事情来说可能效率低下。我想知道设置存储桶是否有意义,每个存储桶可以是 Book (可能会产生数百万个“Book”存储桶)。也许这是一个坏主意...
这可以用二级索引完成吗?
我想保持这个简单......
我是Riak的新手,我正在努力找到完成可能相对简单的事情的最佳方法。感谢Stack Overflow社区提供的任何帮助。谢谢!
答案 0 :(得分:1)
最有效的方法是将孔书存储为一个对象,并将其页面复制为另一个单独的对象。 优点:
缺点:
Riak是关于可用性可预测的延迟,所以如果您将使用类似2i的东西来收集结果,那么它将产生不可预测的时间查询,这将随页码增长
答案 1 :(得分:1)
在Riak中建模主 - 细节关系的常用方法是让主记录包含详细记录ID列表,可能还有一些关于详细记录的信息,这些信息在决定要检索哪些详细记录时可能很有用。 / p>
在您的示例中,您可以使用两个名为“books”和“pages”的存储桶。 “书籍”存储桶中的主记录将包含有关该书整体的元数据和信息以及书中包含的页面列表。每个页面将包含保存页面数据的“页面”记录的ID以及相应的页码。如果你是希望能够按章查询,您还可以添加有关某个页面属于哪个章节的信息。
'pages'存储桶将包含页面文本,并可能链接到该页面上包含的图像和其他媒体数据。这些数据可以存储在另一个存储桶中。
为了获得特定页面或一系列页面,首先要从“书籍”桶中检索主记录,然后根据记录的内容检索适当的页面。即使这需要几个GET操作,它们都是基于密钥的直接查找,这是从Riak检索数据的最有效和可扩展的方式,因此它将执行并且可以很好地扩展。
这种方法还可以简化页面和/或章节的顺序,因为只需要更新主记录。但是,添加,删除或修改页面需要更新,添加或删除主记录以及一个或多个详细记录。
您当然也可以通过向对象添加二级索引并基于此查询来解决此问题。然而,Riak中的二级索引查询必须包括对分区的覆盖集(通常是环大小/ n_val)的处理以满足请求,因此对系统施加更多负载并且通常导致比检索分区更高的延迟。通过直接键查找包含键的单个对象(只需涉及实际存储对象的分区)。
虽然在插入或删除页面/条目时维护包含索引的单独对象会增加一些额外的工作,但这种方法通常会导致更高效的读取,因为只需要直接键查找。如果您的应用程序对读取很重要,那么使用这种方法可能是有意义的,而二级索引对于大量写入应用程序可能更有效,因为插入和修改会以更昂贵的读取为代价变得更便宜。但是,您可以随时添加二级索引以防万一,以保持您的选项打开。
在这种情况下,我通常会建议执行一些基准来测试解决方案,并选择最符合您特定性能和扩展要求的解决方案。