论坛首页 综合技术论坛

NoSQL数据库探讨之一 - 为什么要用非关系数据库?

浏览 118386 次
该帖已经被评为精华帖
作者 正文
   发表时间:2009-11-25  
风向逆转 写道
期待robbin的后续文章。
公司产品在用TT/TC,且发布在mixi.jp上。藉此robbin的介绍文章,回头研究一下TT/TC在我们产品上面的使用


莫非是阳光牧场? social game需要很高的并发写数据请求,用TT/TC倒是很合适。
0 请登录后投票
   发表时间:2009-11-25   最后修改:2009-11-25
keakon 写道
平时经常做GAE的开发,所以经常接触BigTable。

感觉这个GAE上的BigTable的限制还是比较多的。例如无索引就不能查询,不能对2个以上的属性进行不等于操作(如>、<),使用不等于操作必须先对该属性进行排序,事务操作时不能使用查询,事物中操作的实体必须在同一个实体组…

我不知道其他NoSQLDB是不是也有这些问题,但对开发肯定有影响。例如想找最近10天评价最高的几篇帖子就是不可能的,因为对时间进行了不等于操作,就必须先对时间排序,之后才能对评价进行排序。

非关系型还有个缺点就是表之间的关联。Join操作不能用了,于是得取出一个表里所有符合的列,再对另一个表进行多次的查询(虽然BigTable也支持IN操作,但限制数目最多20,而且内部实现是多个并发的=操作)。如果涉及到3个以上的表的话,这种操作的效率和代码量更是不可接受的。


你还是在用关系数据库SQL的思路去套BigTable,对于NoSQLDB来说,不是简单的换个数据库就可以了,你的编程思路和设计要相应的转变。

keakon 写道
至于读写的效率,我感觉BigTable也并没有什么优势。
昨天刚写了一个测试,保存1个含10个字符串属性的实体到数据库,约需30ms;获取约需10ms(我是直接用key来获取,没有进行查询操作):
http://test.latest.keakon.appspot.com/test

之前还测试过大批数据的存取:保存、删除100个含1个字符串的实体,需700~800ms,500个需3000~4000ms;获取10个约需40ms,100个需150~200ms,500个需300~400ms,1000个需500~600ms。(500和1000是写、读的最大限制了,不能继续往下测试了。)
http://gaejava.appspot.com/

因为大批数据的操作是由数据库完成的,网络延时可以忽略了。我不知道GAE后台部署了多少数据库服务器,但肯定是个集群,所以这种测试也不只是使用一个数据库。
由于写操作基本和数目成正比,所以差不多就这个性能了,每个约7ms;读似乎还能提速,但应该达不到1W的并发。注意这还只是操作的记录数,而不是操作的次数(操作只有1次)。如果按每次读10个来计算,能达到1000的并发就不错了。
顺带一提,现在我的这个模型(表)的大小约100MB(含索引),而MySQL要达到这个性能应该是很轻松的。

当然,对我来说根本用不到1000并发,GAE本身也有每分钟3万次页面请求的配额限制。
而数据量的话,我那个blog有20篇日志,用了约500个实体,占用约300KB数据库空间。要到GB级的话,我得写十万篇日志,对个人网站来说基本不可能…

事实上BigTable给我的感觉就是限制太多,性能一般,优点用不上。
虽然对搜索引擎有用,但那至少是几十万台服务器的,否则如何支撑几十亿的PV?[/url]


我主贴已经很明确的指出,BigTable这种分布式的数据库系统面向的问题领域是横向扩展,而不是为了追求高性能高并发读写的速度,而且我已经举出来Cassandra的例子着重谈了这点,显然你还没有理解BigTable的应用场合以及要解决的是什么问题。

BigTable要解决的是scale的问题,例如海量用户比方说几亿几十亿用户同时去访问这个系统,而这个系统不会被如此巨大访问量冲溃的问题,具体到单个用户,他读写速度只要在可以接受的范围就可以了,并不要求单个用户的请求在极快的时间内处理完毕。




0 请登录后投票
   发表时间:2009-11-25   最后修改:2009-11-25
AreYouOK? 写道
我在工作中也遇到很多问题,关系数据库确实有些力不从心了,但是不使用关系数据库,面对复杂的查询,没有好的解决方案。
从这篇文章的介绍看,我对MongoDB最感兴趣,期待后续。

我的需求和这里列出的Web2.0的网站需求还不太一样。我的场景是:
  • 数据量非常巨大,写操作特别多。数据量可以说是无限的,就看系统能处理多少,如果能处理更多就要接入更多的数据(一般来说我们只接入了部分数据)。
  • 读操作非常少,可以用每天多少次来衡量(就那么几个使用人员,他用的时候才有查询操作),但是一旦有查询操作,往往都是重量级的。
  • 查询操作可以稍微慢点,能在5秒内出来就不错了,如果进行复杂的查询,30秒出来也算不错了。10分钟甚至1个小时才查出结果,是非常不好的,但是能出来总比不能要好。
  • 写操作允许丢失少量数据,但是整个数据库的完整性要有保证
  • 数据最好能够压缩存储


在某个项目里面,数据量大的时候大约每天40、50G,使用postgresql,居然也支撑了下来,但是查询非常慢。接下来的一些项目数据量会更大,可能会有这个量的100倍以上,目前没有好的办法,只能从数据源头先做过滤。

我在1年前,开始尝试进行一些探索,根据产品需求特点,使用自定义的数据格式存储。目前能够解决的问题有:
  • 对数据进行简单的解析和压缩存储
  • 能够对压缩的数据进行简单的查询(指定数据源、时间范围、关键字),查询较慢,但是比SQL有一个好处,就是能看见当前查询到哪个时间点了,而不是像SQL一样,等运行完了才能给用户看到
  • 高性能的写入。目前在我的笔记本上进行简单的测试,每秒2万条的UDP包,丢包率是0.5%,在复杂的环境下性能是会下降的,但服务器的性能会更好

不幸的是,我只有很少的时间能投入到这上面,有时候几个星期都没空去弄,所以到现在还有很多要完善的地方,没有在项目里面实用。有时候我都怀疑这条路是不是走错了。

目前没有解决的问题是高性能的、对数据的复杂查询。数据可以分为2部分,原始数据和格式化后的数据,目前我这里只解决了原始数据的问题,对于格式化数据的复杂查询,还是需要类似关系数据库的功能才行。这也是我对MongoDB比较感兴趣的原因。


这种应用场景比较适合MongoDB,很多MongoDB的应用都是用Mongo来存储海量的日志数据,然后对日志数据进行查询和分析。 应付几十上百GB的单表进行SQL查询,关系数据库的查询性能下降的非常可怕,动辄几十秒到几分钟,而Mongo主要特点就是对海量存储数据的查询速度非常快,查询速度往往在毫秒级别搞定。

0 请登录后投票
   发表时间:2009-11-25  
bingobird 写道
非关系型数据库更多的是解决海量数据时主键型查询及更新的问题。
它有个比较难解决的就是非主键的查询,比如取一用户的所有好友列表。

大数据量下我们目前解决方法是通过搜索引擎或数据库集群+缓存处理,但前者用作查询并不合适,后者mysql及pg在这块的支持还不是很好,收费的又太贵。


这个需求一点都不难,关键还是你对数据存储结构的设计是不是合理,比方说用Redis的话,用单独的Set来保存某个用户的好友列表: user:id:friends => [friend_id1, friend_id2, ...],如果是用TC的话,就更简单了,用一个单独的表保存用户订阅关系,然后直接查询就行了。
0 请登录后投票
   发表时间:2009-11-25  
ahuaxuan 写道
数据库革命还谈不上,这些东西最多就是弥补数据库的缺点,在整个架构中,属于和数据库相互补充的这个一个角色。

当然我也想知道是否有大型网站完全不用数据库的,知道的同志出来说说。


mixi.jp在极少数功能里用了TC,大部分功能还是memcached + mysql架构。
其它网站不知道,完全不用关系数据库不太可能吧,Key-Value数据库应该是弥补关系数据库缺点的,不是代替关系数据库的。
0 请登录后投票
   发表时间:2009-11-25  
robbin 写道
bingobird 写道
非关系型数据库更多的是解决海量数据时主键型查询及更新的问题。
它有个比较难解决的就是非主键的查询,比如取一用户的所有好友列表。

大数据量下我们目前解决方法是通过搜索引擎或数据库集群+缓存处理,但前者用作查询并不合适,后者mysql及pg在这块的支持还不是很好,收费的又太贵。


这个需求一点都不难,关键还是你对数据存储结构的设计是不是合理,比方说用Redis的话,用单独的Set来保存某个用户的好友列表: user:id:friends => [friend_id1, friend_id2, ...],如果是用TC的话,就更简单了,用一个单独的表保存用户订阅关系,然后直接查询就行了。

这个例子还是太简单了,比较复杂的查询用key-value应该是没法实现的,比如论坛用户积分top10列表。
所以一般是需要借助一些外部search engine来做
0 请登录后投票
   发表时间:2009-11-25  
非常期待下篇文章。

我也是选择了,Redis,TT/TC和MongoDB了。
主要是解决了不同问题,其次是php能够很好支持也是一大原因之一。
0 请登录后投票
   发表时间:2009-11-25  
谢谢robbin分享这么难得的文章!
0 请登录后投票
   发表时间:2009-11-25  
hideto 写道
robbin 写道
bingobird 写道
非关系型数据库更多的是解决海量数据时主键型查询及更新的问题。
它有个比较难解决的就是非主键的查询,比如取一用户的所有好友列表。

大数据量下我们目前解决方法是通过搜索引擎或数据库集群+缓存处理,但前者用作查询并不合适,后者mysql及pg在这块的支持还不是很好,收费的又太贵。


这个需求一点都不难,关键还是你对数据存储结构的设计是不是合理,比方说用Redis的话,用单独的Set来保存某个用户的好友列表: user:id:friends => [friend_id1, friend_id2, ...],如果是用TC的话,就更简单了,用一个单独的表保存用户订阅关系,然后直接查询就行了。

这个例子还是太简单了,比较复杂的查询用key-value应该是没法实现的,比如论坛用户积分top10列表。
所以一般是需要借助一些外部search engine来做


1、NoSQLDB和SQLDB不是一个完全的取代关系,而是互补的关系,不要假设所有的应用场景都强迫自己用NoSQLDB。

以上面那个用户订阅的例子来说,很多情况下是需要用NoSQLDB存储的,比方说twitter类型的应用,对用户的follows列表有非常高的读取的需求,如果存储在关系数据库里面,SQL负载会太重,不如NoSQLDB速度快,而且并发读取性能更高。所以那是一个很适合用NoSQLDB的场景。

而你举例论坛top积分用户,这个需求根本就不需要高性能读取,甚至也不需要实时性,完全没有必要用NoSQLDB,而且即便是用SQL数据库,也不能很好的处理这种需求,以JavaEye的博客排行榜为例,生成月度和年度博客排行榜是一个非常耗时的SQL查询,根本就不能搞成实时查询,我们是每天晚上跑一个复杂的SQL语句,把结果生成html片段保存下来,然后页面直接拼接起来显示。

2、即使用NoSQLDB单纯的取论坛用户积分top10列表,TT/TC也不过就是一条查询而已,和SQLDB没有任何区别,TC的table存储结果本身就支持条件查询,分页结果集和排序。
0 请登录后投票
   发表时间:2009-11-25  
robbin的看法很独到。
对于bigtable,不能用SQL的用法来要求它。几年之后,随着NoSql的普及,大家会把它用在它适合发挥的地方,同时形成一套成熟的用法。
0 请登录后投票
论坛首页 综合技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics