分享 为什么我从 MongoDB 迁移到 PostgreSQL

Rei · 2014年07月19日 · 最后由 JeskTop 回复于 2014年08月08日 · 8698 次阅读

想当年,多少人头脑发热把数据库从 sql 转到 mongodb

你这不算是迁移。因为你的新的卖书网站一开始就选型了 PostgreSQL, 压根和 mongoDB 木有关系。

#2 楼 @jeff_duan 新站从老站系统二次开发,老站原本是 mongodb,数据迁移脚本在这里 https://github.com/chloerei/campo/blob/import/lib/tasks/import.rake

#2 楼 @jeff_duan 另外这个标题的主语是“我”。

迁移作为一个词语时,它的意思是离开原来的所在地而另换地点或由于自然力的作用从一地移向另一地。在心理学中,它指的是是一种学习对另一种学习的影响,指在一种情境中获得的技能、知识或态度对另一种情境中技能、知识的获得或态度的形成的影响。

http://baike.baidu.com/view/621740.htm

最近也要做标签功能,不过没想到可以用 pg 的 array

有个问题,如果用 array 存储标签,要如何对标签汇总(生成标签云)?

推荐这个视频 Rails Conf 2013 Postgres, the Best Tool You're Already Using by Adam Sanderson

演示文档

http://adamsanderson.github.io/railsconf_2013/

发现一个不错的 postgresql 博客: http://francs3.blog.163.com/

#6 楼 @saiga 再加个统计表,或者回到关联表的实现。

好文。

再补充一个关于 link/denormalize/cache 的观点,来自 Sarah(Dispora 主要开发者之一) 的一篇文章: http://www.sarahmei.com/blog/2013/11/11/why-you-should-never-use-mongodb/

Dispora 最初是基于 MongoDB 开发的,后来因 production 中的种种问题,后来被迫转到了关系型数据库。

Denormalization 是 MongoDB 的特定,但同时也是一个应用场景的很大限制。

有一段是关于 link(relationship) 的

Whether you’re duplicating critical data (ugh), or using references and doing joins in your application code (double ugh), when you have links between documents, you’ve outgrown MongoDB. .... If your data looks like that, you’ve got documents. Congratulations! It’s a good use case for Mongo. But if there’s value in the links between documents, then you don’t actually have documents. MongoDB is not the right solution for you

她认为 MongoDB 的 denormalize 在本质上就是 cache, 而把 cache 和实质数据存储混在一个层面有很大的问题。如果用关系型数据库,大不了使用核武器 -- 摧毁所有 cache 然后重建。但混在一起的话连这个核武器都没有了。

You can always delete the entire activity stream record out of your cache and regenerate it from your consistent backing store. It may be slow, but at least it’s possible.

What if there is no backing store? What if you skip step 1? What if the cache is all you have?

When MongoDB is all you have, it’s a cache with no backing store behind it. It will become inconsistent. Not eventually consistent — just plain, flat-out inconsistent, for all time. At that point, you have no options. Not even a nuclear one. You have no way to regenerate the data in a consistent state.

When Diaspora decided to store social data in MongoDB, we were conflating a database with a cache. Databases and caches are very different things. They have very different ideas about permanence, transience, duplication, references, data integrity, and speed.

看完这后,我觉得我还是用 mysql 吧

#10 楼 @billy 我以前看过这篇文章,不太同意前半篇举的例子

MongoDB 提供了嵌入文档的功能,不意味所有能嵌入的地方都要嵌入,这种多个地方共享的数据不应该嵌入。这像是故意用错然后说工具不好。

我会这样设计:

// users
{
  _id: 1,
  name: Joe
}

// streams
{
  _id: ...,
  user_id: 1,
  activities: [id, ...]
}

// activities
{
  _id: ...,
  user_id: 2,
  title: 'today',
  body: 'go fly a kite',
  like_ids: [3, 1]
}

页面视图再缓存一次。

用关联表实现标签云很方便啊,难道是 MySQL 用惯了的缘故

#12 楼 @Rei 既然这样设计了,为什么不用 sql 呢

没什么特殊要求,还是 sql 吧!不过我还未尝试过 psql

结构型的元数据存 Mysql,大量的自包含的数据(如交易日志)存 NoSQL,充分结合 2 者的好处。没有必要只用一种,NoSQL 概念很火,但是实际上面应用还是要多多考虑。我听过 netfix 的分享,他们把 oracle 换成 NoSQL 之后,发现有一些问题,主要是数据完整性方面的,然后他们就把架构改成了我上面说的那种

为什么我从 PHP 迁移到了 Ruby? 为什么我从 Ruby 迁移到了 Nodejs? 为什么我从 Nodejs 迁移到了 Go? ......

对于类似这样的标题,我总是想说:你好蛋疼。

#6 楼 @saiga 标签云又不需要实时生成,每天遍历一次所有标签就好了。

#19 楼 @nouse 把实时变成了定时是倒退。

一个功能如果能设计成即时的就不要设计成延时的,能够设计成延时的就不要设计成定时的,即使是统计类功能——Google Analytics Real-Time 报告有感。

每次遇到开发者说“这个数量每天晚上统计一次就行了,用户不会发现不一致的。。”“这个排名几天统计一次就行了,用户不关心的。。”,我就想问“既然这么不重要做这东西干什么”。

#18 楼 @sefier 从 ruby 到 nodejs 为了异步,node 到 go 为了分布。有啥蛋疼的地方?

#19 楼 @nouse 目前的应用要将标签细化到用户级别,每个用户都有自己的标签集合,延时不合适。还是用回传统的中间表好了

#20 楼 @hooopo 貌似很正确的扯淡,标签云用异步实现当然没有问题

珍爱生命,远离 mongodb

@vincent 。。。。。。。

#22 楼 @SharpX 你强调的是“没问题”(可以将就?),我强调的是 Best Practice。我们讨论的不是一个问题。

#20 楼 @hooopo “既然这么不重要做这东西干什么"

很遗憾,如果程序员可以影响到产品功能那这个世界会美好很多,程序员只要做出来,而且不影响服务器的性能就是胜利。也不要和我说“不想参与产品功能设计的不是好程序员”,正是要先完成本职工作才能有话语权。

@hooopo 从 Google Analytics 报告就宣称自己的做法是 Best Practice,那我的做法也是 Best Practice。

#26 楼 @nouse 那就谈本职工作好了,如果 GA 的例子不认同,还是回到标签云。

标签云的目的是为了反应标签的流行度。而所谓流行都是有时间维度来参照的,流行是要反应当下状况,这是一个相对即时需求。没有一个产品会直接设计成“我就要昨天的标签的热度”,当然,如果一个网站访问访问量不大,昨天标签的热度也”没问题“,个人博客一年计算一次热度也“没问题”。不过没有一个产品会为访问量不大而设计,一旦我们把讨论前提都加上访问量不大这个定语,所有讨论都失去了意义。

我觉得,这不是“完成了本职工作”,而是一个程序员式的误解和偷工减料。

#27 楼 @hooopo 正是因为访问量大才要缓存,数据库资源那么宝贵,为何要浪费在计算热门标签上?再说既然有时间维度,可以每小时,每分钟生成,为何要每次请求都要生成?

如果这也是偷工减料,那我只能说写程序就是要偷工减料,比如以前流行的 45 度角伪 3D,就是为了在资源有限的时候达到最好的效果。

如果是用户相关的另当别论,因为这是一个个性化需求的,而且访问量也不大。

#27 楼 @hooopo 钻牛角尖了,在资源有限的前提下,当然要有些取舍。

不蛋疼么,标签云这种东西丢给 CouchDB 最合适吧

#30 楼 @bhuztez CouchDB 实现标签云是怎么样的?

#25 楼 @hooopo 我强调的是“异步统计”,谢谢。

你确定 Google Analytics 不是采用异步实现的?我觉得你说的“把实时变成了定时是倒退。”一开始就搞错了概念,我们讨论的是数据的收集和存储,你讲的是用户是不是可以第一时间看到前面的统计结果,这是两个问题,Google Analytics 的实时是说在 Dashboard 上可以“实时”看到最近的统计,他的数据收集也是异步处理的,Google 并不是你跑去点击 report,然后他在跑去帮你统计。

系统会不间断地更新数据,每当有用户浏览网页时,您都可以在几秒钟内看到相关的报告。

至于标签云,标签有变化后,触发统计事件,根据你的访问量的情况写到 redis 或者 db 中,这是我觉得比较好的实践,从需求上讲 @nouse 说的每天统计也是很常见的,当然你可以说每个小时计算一次比较好或者按照事件触发比较好,但是你后面举得几个夸张的例子完全跟讨论无关

#28 楼 @nouse #29 楼 @zgm

我一直没有谈实现问题呀 总结一句话:实时是刚需,技术实现难。

我当然知道什么是权衡,但大家也要明白什么是直接需求,什么是退而求其次呀。

PostgreSQL 还是蛮强大的,除了 array 和 hstore 外还可以直接支持 json,简单的嵌套数据和少数的可变字段都可以存到 json 里面去。

#21 楼 @saiga 呵呵,那前几年从 PHP 迁移到 Rails,然后又从 Rails 迁回到 PHP 的怎么解释呢?真有你说的那么简单吗?

#35 楼 @sefier 几年前有一家英国报社从 Java 转到 Scala 的,项目主管给出的原因是:Scala 不用强制分号。事实上,这种蠢事还真不少,大多图个新鲜完全不考虑其他因素。但不代表其他人也一个尿性,别人写了一长篇文章来解释,你来一句“好蛋疼”

#35 楼 @sefier 如果不试试新工具,就不会知道有些已有工具很难办的功能,在新工具里很容易实现。举个例子:定制表单、地理位置搜索、Timeline。

#36 楼 @saiga 这样说就对了嘛,你前面的回复就是强词夺理。不过我坚持认为这样的标题,毫无营养。

一直在用 maridb 和 postgresql 新的东西太多坑了

40 楼 已删除

#39 楼 @Lucifer 有什么明显的坑,求赐教。因为确实打算转去使用 pg

42 楼 已删除

#42 楼 @fwdb15 不要用回帖招聘,没有发帖权限邮件联系 [email protected]

#37 楼 @Rei 37 楼说的用新工具那三个容易实现是指?

#44 楼 @flowerwrong

  1. 支持 key-value 的数据库,Mongodb/PostgreSQL
  2. 内置地理位置类型和索引的数据库,Mongodb/PostgreSQL(需扩展)
  3. 内存队列,Redis

我想知道,用 PostgreSQL 后,因为事务的问题,参考:https://ruby-china.org/topics/19499?page=1#reply28 隔离级别是修改为repeated read还是说使用默认的+乐观锁呢?

需要 登录 后方可回复, 如果你还没有账号请 注册新账号