ltf*_*hie 5 rdbms couchdb mongodb nosql riak
为了跟进我关于使用nosql建模关系数据的问题,我已经阅读了几篇关于这个主题的文章:
他们似乎建议nosql可以处理规范化的关系数据.
因此,让我们继续我之前的例子,一个CMS系统,它有两种类型的数据:文章和作者,其中文章有作者的引用(通过ID).
以下是系统需要支持的操作:
如果相同的数据存储在RDBMS上,我想了解这些操作的性能. 特别是,请指定操作是否使用MapReduce,需要多次访问nosql商店(链接)或预加入
我想限制讨论基于文档的 nosql解决方案,如mongodb,couchdb和riak.
编辑1:
Riak和Mongodb可以使用Spring数据项目
只想为任何可能好奇的人提供CouchDB答案.:)
如上面的第一个答案所述,将作者文档嵌入到文章文档中是不明智的,因此下面的示例假设两种文档类型:文章和作者.
CouchDB使用通常用JavaScript编写的MapReduce查询(但可以使用Python,Ruby,Erlang等).MapReduce查询的结果在第一次请求时存储在索引中,并且存储的索引用于所有将来的查找.在进一步请求时,对数据库的更改将添加到索引中.
CouchDB的API完全基于HTTP,因此对数据库的所有请求都是各种URL的HTTP谓词(GET,POST,PUT,DELETE).我将列出MapReduce查询(用JavaScript编写)以及用于从索引请求相关结果的URL.
1.通过id和作者一起获取文章
执行此操作的最简单方法是两个直接文档查找:
GET /db/{article_id} GET /db/{author_id}
...其中{author_id}是从文章的author_id字段获得的值.
2.获取特定作者的所有文章
MapReduce的
function (doc) {
if (doc.type === 'article') {
emit(doc.author_id, doc);
}
}
Run Code Online (Sandbox Code Playgroud)
GET /db/_design/cms/_view/articles_by_author?key="{author_id}"
...其中{author_id}是作者的实际ID.
3.查找按创建日期排序的作者的前10篇文章
MapReduce的
function (doc) {
function arrayDateFromTimeStamp(ts) {
var d = new Date(ts);
return [d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds()];
}
var newdoc = doc;
newdoc._id = doc.author_id;
newdoc.created_at = arrayDateFromTimeStamp(doc.created_at);
if (doc.type === 'article') {
emit(newdoc.created_at, newdoc);
}
}
Run Code Online (Sandbox Code Playgroud)
可以?include_docs=true
在视图请求中使用CouchDB 中的样式"连接" .如果在emit(第二个参数)的值侧包含"_id"键,则添加include_docs=true
到查询参数将包含指定的"_id"引用的文档.在上面的情况中,我们将替换文档自己的"_id"(我们不再需要)与引用作者的"_id"(文章文档中"author_id"的值).使用相关作者信息请求前10篇文章如下:
GET /db/_design/cms/_view/articles_by_date?descending=true&limit=10&include_docs=true
请求该URL将返回最近10篇文章的列表,格式类似于:
{"rows":[ { "id":"article_id", "key":[2011, 9, 3, 12, 5, 41], "value":{"_id":"author_id", "title":"..."}, "doc":{"_id":"author_id", "name":"Author Name"} } ]}
使用相同的索引,您可以获得包含或不包含作者数据的任何年,月,日,小时等粒度的所有文档的列表.
还有一些方法可以使用视图整理将多个文档聚合在一个文档中(如CMS中引用不同内容的页面).我在7月份为CouchConf做的这些幻灯片中有一些关于如何做到这一点的信息:http://www.slideshare.net/Couchbase/couchconfsfdesigningcouchbasedocuments
如果您有任何其他问题,请告诉我.
对于 MongoDB,您不会使用嵌入式文档作为作者记录。所以预连接已经结束,需要多次访问数据库。但是,您可以缓存作者,并且只需为每个记录进行第二次访问。您指出的查询在 MongoDB 中非常简单。
var article = db.articles.find({id: article_id}).limit(1);
var author = db.authors.find({id: article.author_id});
Run Code Online (Sandbox Code Playgroud)
如果您使用 ORM/ODM 来管理应用程序中的实体,这将是透明的。不过,这将是两次数据库之旅。不过,它们的反应应该很快,两次点击根本不应该被注意到。
查找给定作者的文章正好相反......
var author = db.authors.find({id: author_name}).limit(1);
var articles = db.articles.find({author_id: author.id});
Run Code Online (Sandbox Code Playgroud)
同样,两个查询但单个作者的获取应该很快并且可以轻松缓存。
var articles = db.articles.find({}).sort({created_at: 1}).limit(10);
var author_ids = articles.map(function(a) { return a.author_id });
var authors = db.authors.find({id: { '$in': authors_ids }});
Run Code Online (Sandbox Code Playgroud)
最后,再次提出两个查询,但只是稍微复杂一点。您可以在 mongo shell 中运行这些命令以查看结果。
我不确定这是否值得编写一个地图缩减来完成。几次快速往返可能会有更多的延迟,但 mongo 协议相当快。我不会对此过于担心。
最后,这样做的实际性能影响...由于理想情况下您只会查询文档中的索引字段,因此它应该非常快。唯一的额外步骤是第二次往返以获取其他文档,具体取决于您的应用程序和数据库的结构,这可能根本不是什么大问题。您可以告诉 mongo 仅分析超过给定阈值(打开时默认为 100 或 200 毫秒)的查询,这样您就可以随着数据的增长密切关注程序所花费的时间。
RDMS 不提供的功能是更容易分解数据。当您将应用程序扩展到 CMS 之外以支持其他事物但使用相同的身份验证存储时,会发生什么情况?它现在恰好是一个完全独立的数据库,在许多应用程序之间共享。跨数据库执行这些查询要简单得多 - 对于 RDMS 存储,这是一个复杂的过程。
我希望这对您的 NoSQL 发现有所帮助!
归档时间: |
|
查看次数: |
2562 次 |
最近记录: |