-
Notifications
You must be signed in to change notification settings - Fork 4
Description
排行榜中需要用到这个功能,但是将来很可能不用mongdb做排行榜了,感觉不太合适。记录一下。
有几个方法可以复制一个集合
参考资料:http://stackoverflow.com/questions/8933307/clone-a-collection-in-mongodb
函数遍历
db.demo1.categories.find().forEach( function(x){db.demo2.categories.insert(x)} );这里跑题一下。在shell中,find有些机制需要了解一下。摘自《MongDB权威指南(第二版)》。
调用 find 时,shell 并不立即查询数据库,而是等待真正开始要求获得结果时才发 送查询,这样在执行之前可以给查询附加额外的选项。几乎游标对象的每个方法都 返回游标本身,这样就可以按任意顺序组成方法链。例如,下面几种表达是等价的:
> var cursor = db.foo.find().sort({"x" : 1}).limit(1).skip(10); > var cursor = db.foo.find().limit(1).sort({"x" : 1}).skip(10); > var cursor = db.foo.find().skip(10).limit(1).sort({"x" : 1});此时,查询还没有真正执行,所有这些函数都只是构造查询。现在,假设我们执行 如下操作:
> cursor.hasNext()这时,查询被发往服务器。shell 立刻获取前 100 个结果或者前 4 MB 数据(两者之 中较小者),这样下次调用 next 或者 hasNext 时就不必再次连接服务器取结果了。 客户端用光了第一组结果,shell 会再一次联系数据库,使用 getMore 请求提取更 多的结果。getMore 请求包含一个查询标识符,向数据库询问是否还有更多的 结果,如果有,则返回下一批结果。这个过程会一直持续到游标耗尽或者结果全部 返回。
虽然不确定驱动中是否类似,不过驱动提供了和shell类似的语法,譬如nodejs中不是cursor.hasNext()而是cursor.nextObject(),不是forEach而是each。猜测应该是一样的原理。这样也就不需要担心同时把大量数据加载到nodejs导致进程崩溃的问题。
回到主题,这个方法并不会造成写锁,就是普通的查询和插入。也就是无法复制瞬间的数据快照。(有人的测试数据是每秒2700条处理。想一下百万数据得多久)
官方给了一个更直观的方法。
copyTo
http://docs.mongodb.org/manual/reference/method/db.collection.copyTo/
不过有人提示:不要在生产环境使用,因为这东西会锁住该mongo实例上其他所有的操作。
那么如果是主从,在从上复制呢?这样意义也不大,从上数据无法恢复到主,复制出来也没有意义。
cloneCollection()
这个不多说,是远程复制。不是在本库中复制
mongoexport
mongoexport -d db_name -c src_collection | mongoimport -d db_name -c dst_collection --drop
这个说是最快的方法,个人感觉是最方便,快到不一定。
方便的原因就是一句话搞定。
mongodump
这个就两条了:
mongodump -d db_name -c src_collection
mongorestore --drop -d db_name -c dst_collection ./dump/db_name/src_collection.bson
需要生成一个文件。
但导出来说,mongoexport用的没有mongodump多。mongodump速度也非常快。
这是mongodump的优势
同时mongorestore就不那么给力,速度被质疑非常慢。(质疑的例子中,mongodb并没有停掉)
这个方法的优势是一切都在binary层面做的,不会有数据格式的转换。譬如find+insert方式,就会由不同的语言驱动导致数据类型变化,如int变成了double等。
总结
其实复制一个集合,这个本身需求就有点非常规。上面方法有诸多限制,可以根据自己的场景选择一个合适的,如果没有合适的,建议还是换一种实现方式。
mongodb我一直想把它作为内存缓存+传统的数据库的合体来用,又具备内存缓存的高速、同时数据操作锋利丰富、类似传统数据库、此外持久化也比较靠谱。相比之下,redis更擅长消息推送、天然排序-排行榜之类的事情。这些需要,mongodb做起来就比较吃力,需求一复杂,甚至会吃力到实现了但线上不可用。