Mongoid如何处理对类定义变更?created at |
|
在Python的MongoEngine(MongoDB ODB)中,数据和类定义绑定,一旦修改类,比如增加获删除一个字段/方法,再取出旧对象的数据就会出错,唯一的办法是写一个“一次性”程序,将所有旧的类定义转化成新的类定义对象,非常麻烦。
请教一下@Rei,campo用的Mongoid是怎么处理这种问题的?
Mongoid如何处理对类定义变更?created at |
|
在Python的MongoEngine(MongoDB ODB)中,数据和类定义绑定,一旦修改类,比如增加获删除一个字段/方法,再取出旧对象的数据就会出错,唯一的办法是写一个“一次性”程序,将所有旧的类定义转化成新的类定义对象,非常麻烦。
请教一下@Rei,campo用的Mongoid是怎么处理这种问题的?
|
差不多的,数据迁移一向是需要谨慎测试和备份但是又一次性的活。 mongoid 修改字段取旧数据不会出错,只会缺失字段值。 试过用 mongoid_rails_migrations,相当于一次性的脚本。有些可以重复使用或者稍微修改可以适应新需求的放在 lib/task。 如果 MongoEngine 修改字段会报错,那么这个映射层太紧了。Mongodb 本身功能足够丰富了,不需要用太厚重的包裹。mongoid 定义 field 只相当于添加一些便利方法,文档对象还是可以像 hash 那样用。 |
|
|
不过换个角度看,数据模式不对就报错强制开发者写迁移脚本,适合那些希望清楚知道数据库里面有什么数据的人,也算一种风格。 |
|
|
updated at
好的,明白了。 如果只能有这种模式的话,似乎对频繁修改模型的网站来说很苦阿,修改一下,更新对象数据,再修改一下,再更新对象数据。。。 话说NoSQL的两大特点:1,速度;2,灵活性;用OXM来使用NoSQL,似乎就是丢掉了灵活性,只剩下速度了,但要求更大的灵活性,似乎又要什么都自己来写了,真是矛盾呢。 |
|
|
用mongodb的时候虽然会用ODM,但本质还是操纵文档。模式变更的时候需要考虑:老数据有没有需要清理的过期数据、有没有需要新增的必须字段、有没有需要转换处理的字段。有的话就要写迁移脚本。 虽然没了数据库模式迁移,但还是有数据迁移。 |
|
|
updated at
刚才用100kb的小文本文件,用1000次循环,在我的本本上,对redis(via redis-py),mongodb(via py-mongo)和ZODB(Zope的数据库,OODB,直接使用key-value模式,没有依附其他数据结构)进行了小规模写入和读取测试。 发现一些结果,有些有点意外: 逐次写入: 也就是
Mongodb没有强制将数据写入硬盘的函数,忽略。 连续写入 也就是
使用Mongodb的collection.insert(record),速度比Redis.set(record)稍快一点,MongoDB 1.x秒,而Redis 2秒左右,考虑到Mongodb和Redis默认都是使用异步模式,速度相差不大,算是意料之中。 读取
无索引情况下,ZODB是0.1x,Mongodb是1秒多,Redis是0.3秒。 有索引/缓存情况下,ZODB是0.004秒,MongoDB仍是1秒多,比原来快了零点几秒,Redis是直接key-value,没有东西可索引的,速度和无索引情况一样。 暂时总结 Redis的写入情况和MongoDB相似,但Redis的读取速度比MongoDB稍快。 |
|
|
redis 的结果比较奇怪,它应该超过 memcached 的速度这一级别。我有空也测一下。 |
|
|
@huangz |
|
|
updated at
@reus 正想去看看Redis的save方法的相关资料,你解决了我对save方法的疑问,3Q。 你说的ZODB数据常驻运行时而造成速度优势的问题,我特意分开了写入和读取步骤,发现即使那样,时间还是没有变化,ZODB的读取速度比Redis和MongoDB都快。 我估计造成区别的原因是Redis和MongoDB都是网络服务(如你所说),而ZODB的数据库则是一个文件系统,一个open函数就能将数据读出来,这里是ZODB比Redis和MongoDB都占优势的地方。 但我怀疑这种模式在ZODB数据库包含大量数据之后,是否还能继续保持这种优势,这个要等研究ZODB的原理和代码之后才能有进一步理解。 之后我想做数据量更大的测试,但遗憾地发现我没有那么大的内存,本来还想继续测试,但是想来那么小的数据集表示不了什么,还是就此打住好了。 |
|
|
updated at
环境 Linux mypad 2.6.39-ARCH #1 SMP PREEMPT Tue Jun 7 05:49:02 UTC 2011 i686 Intel(R) Core(TM)2 Duo CPU T6570 @ 2.10GHz GenuineIntel GNU/Linux 条件,100kb文件,循环写入/读取1000次,每个测试方法是分开运行的,比如 python -m unittest testFile.TestCase.testMethod && python -m unittest ... Zodb,同步,第一个是写入时间,第二个是无内存缓存的查询,第二个似乎是有内存缓存的查询。 Ran 1 test in 0.038s Ran 1 test in 0.003s mongodb 异步,第一个是写入时间,第二个是无索引查询,第三个是建立索引的时间,第四个是带索引的查询 Ran 1 test in 1.159s Ran 1 test in 0.002s Ran 1 test in 1.137s redis,默认设置(不带save或bgsave),后面是查询时间 Ran 1 test in 0.296s redis,在所有数据写入之后调用save,后面是查询时间 Ran 1 test in 0.299s redis,在所有数据写入之后调用bgsave,后面是查询时间 Ran 1 test in 0.323s |
|
|
@huangz 要贴脚本啊。 才看明白刚才用的是 redis save。我觉得redis是拿来做半持久化的,当作持久层用是不合适的。 |
|
|
@Rei 似乎勉强一点也可以做数据库用,只是一旦意外down机,会丢失部分数据。。。真刺激阿。。。 |
|
|
@huangz 可以用replication,类似多机热备的结构 |
|
|
@huangz 之前的说法有错误,如果redis配置了使用aof,那是不会遍历整个db的,而只是把增量数据存入磁盘 |
|
|
@reus 是的,正如你所说,有aof之后就不必save了,每次写入数据都追加到数据库最后。 |