文档章节

CouchDB用起来可能不是很舒服

hell0cat
 hell0cat
发布于 2015/08/12 10:51
字数 1519
阅读 7779
收藏 20

最近我花了一个星期研究NoSQL,我有一个400万记录的MySQL速度比较慢,准备迁移到NoSQL上,因为主要是一些JSON格式的文档,本来序列化存在MySQL中的,因为看上了Erlang这个号称非常牛X的平台,挑中了CouchDB,但导入40万有效测试数据,在本地运行的时候,发现速度特别慢(本地机器为2011年的iMac,配备16G内存,根本不弱的),而且查询功能很弱,可能还没到成熟的时候。

CouchDB特点:

面向文档数据库,不需要范式,直接存储JSON就可以,CouchDB默认会生成 _id,_rev 两个键,_id是一条记录(文档)的唯一标识,如果不提供_id,_id会自动生成,也可以手动指定_id,比如用手机号做主键:

{'_id' : '+86186*****', name: '' }

 _rev是其版本号,每更新一次 _rev就会自动发生变化,格式为

5-6a8617596d2adfea245662df0df611ao

,标识第5个版本,后面是HASH签名,可以通过_rev寻找到所有的历史版本,所以用来做需要存储版本的文档系统应该非常不错,比如多人协作修改一篇文档等应用。

CouchDB提供RESTful接口访问,只需要执行http请求就能完成增删改功能,好处是,只需要命令行cURL就可以开始工作了,不需要特别的驱动,比如:获取一篇文档:

curl -X GET http://127.0.0.1:5984/dbname/_id

就可以了,而坏处是,http协议的效率并不高,尤其是如果执行一个页面需要多个请求的时候,用MySQL可以公用一个打开的链接就可以不断执行查询,而用http?得想想怎么样让http复用一个socket链接,所以越是入门简单,后面的麻烦就越多!

CouchDB的查询功能非常弱,CouchDB如何执行查询呢?不同于MySQL,扔一条SQL过去就得了。得为每一次查询创建一个view,view的格式:

{"map": "function(doc){ emit( key,  value); } "}

,这里面的function必须是一个字符串,而不能是javascript的合法语句,所以你写一个稍微复杂一点的语句,得先保证在node/console里调试好,然后把他转换成字符串,然后再构造出合法的json字符串post过去,这个过程非常的痛苦。而且这个view在第一次查询的时候速度会慢的吓死人,40万条数据,执行一次需要的时间大概要5分钟左右,400万条,我就不敢测试了,但stackoverflow上有网友说他跑了4个小时还没跑出结果来,因为这个map可不存在什么优化的地方,map就是一条条在运行,所以不管做什么查询,都要遍历所有doc,能不慢么!

另外,view其实也是像其他普通的记录一样实实在在存在数据库里的,可以通过 _utils 看到,view中是不可以传递变量的(临时view可以),比如在一个库里存在 member 数据有 name, email, city等,需要查询 city为"shenzhen"的member,那么怎么办?第一用临时view: temp_view,构造动态的查询map语句:

curl http://127.0.0.1:5984/dbname/_temp_view?include_docs=true -H 'Content-Type: application/json'  -d \
'{"map": "function(doc){  if(doc.city.match(/shenzhen/) ) emit(doc._id, 1 );  }" }'

最好把这个 _temp_view 存储成永久的view,否则每次查询一个新的city都会很慢的,一旦执行过一次查询,后面的访问就会比较快,但是前提是:得执行过一次查询!

但如果存储为永久view,就需要写死 shenzhen这个字符串在view中,这种传递变量的办法显然是不可取的,非常呆板,难道我要查询一个 city为 shenzhen的就得新建一个 view,那么全国那么多city,是不是每一个都要新建一个city?view这种方式查询真的很愚蠢!

除了temp_view外,到底有没有办法可以动态传递参数的?可以啊 startkey 和 endkey啊,但这两个参数光从名字就可以看出设计的是多么愚蠢了。

好这样查询,先创建一个view,保存为 member/city_query

'{"map": "function(doc){  emit([doc.city, doc._id],   1 );  }" }'

接下来就可以痛快查询啦:

curl \
http://127.0.0.1:5984/dbname/_design/member/_view/city_query?startkey=[shenzhen]&endkey=[shenzhen]
-H 'Content-Type: application/json'

这个语句是不能运行的,需要手动将中括号 [] 转义。看就是这么无聊。

执行的过程是这样的:startkey传递了一个数组参数,只有一个值 shenzhen,在view的map里,emit不再是一个普通的key,而是一个数组,startkey第一个值对应于emit的第一个参数中的第一位即 doc.city, 结果就会检索 city的值>=shenzhen,再指定一个endkey就OK了啊!可以想想,这个map还是会遍历所有的记录!


这样的设计的很低级,而且非常不好用,如果我要查询 正则匹配怎么办?老老实实创建一个新的view? 结果就是如果你的查询比较多样化,里面的view可能比数据还多!

最终我的结论是,不要在大数据上尝试CouchDB,不要在需要频繁查询的地方使用CouchDB,不要在需要大量汇总、分析数据的地方使用CouchDB,他只适合最多几千条数据的小博客、小文档系统,并且不需要各种花式查询的地方,他的性能不如想想中来的那么畅快,而且CouchDB内部存储就是实实在在的文件而已,没有什么优化,提升查询速度也不是CouchDB最近的目标,他们更多关注在功能上而非性能。并且CouchDB的开发初衷是Apache基金会的一厢情愿,并非工程需求,所以如果选择NoSQL,要尽可能找在工程需求中开发出来的数据库。

© 著作权归作者所有

hell0cat
粉丝 35
博文 50
码字总数 25177
作品 0
徐汇
程序员
私信 提问
加载中

评论(14)

春暖花又开
春暖花又开

引用来自“朝花夕拾”的评论

400W MYSQL应该是轻轻松松啊。 我们之前单表1.2亿,100G的数据 都毫秒级响应

吐血 什么数据,服务器啥配置
眸子中记忆斑驳的流年
眸子中记忆斑驳的流年
百万级的数据mysql不会出现瓶颈,你如果在mysql里存文本,肯定会慢,得想办法避免存储大字段
魔力猫
魔力猫
从博文看,这位的SQL水平恐怕也够呛。400W的水平如果数据库无法解决,那么不是数据库的问题而是你的问题。
魔力猫
魔力猫

引用来自“朝花夕拾”的评论

400W MYSQL应该是轻轻松松啊。 我们之前单表1.2亿,100G的数据 都毫秒级响应

引用来自“天下灯火”的评论

你确定咩??没做任何分表操作之类??
如果都是主键,应该有可能。快慢要结合具体业务来判断的。
Windoze
Windoze
HTTP支持keep alive的…………
loki_lan
loki_lan
为什么不用HBase或者Cassandra?
一个大土豆
一个大土豆

引用来自“朝花夕拾”的评论

400W MYSQL应该是轻轻松松啊。 我们之前单表1.2亿,100G的数据 都毫秒级响应
你确定咩??没做任何分表操作之类??
root2000xyz
root2000xyz
怎么不用MongoDB?
朝花夕拾
朝花夕拾
400W MYSQL应该是轻轻松松啊。 我们之前单表1.2亿,100G的数据 都毫秒级响应
朱宏青
朱宏青
postgresql欢迎你
CouchDB 让人头痛的十大问题

下面十条内容来自paperplanes的博主Mathias Meyer,他也是一位NoSQL的实践者,CouchDB就是其钟爱的数据库之一。正所谓爱之深恨之切,在使用CouchDB的过程中,他发现很多不顺手的地方,就是本...

红薯
2012/02/13
4.1K
2
开发者Hasen谈为什么选择CouchDB

【IT168 案例】Hasen是一名熟知分布式技术、Go语言的开发者,他最近在自己的博客上发布了一篇文章,谈到为什么要选择CouchDB作为自己的数据库。   我一直痛恨SQL,所以我总是对NoSQL运动充...

作者:郑柯
2012/10/11
0
0
面向 PHP 开发人员的 CouchDB 基础知识

如果您是位典型的 PHP 开发人员,就不难通过以往的项目得到这样一个结论:在多数(如果不是全部)情况下,为了进行动态数据处理,您都会让 PHP 与数据库后端进行对话;而在这些实例中,99% 的...

红薯
2010/05/02
1K
3
通过 Clojure 使用 CouchDB

本文展示如何使用 Clojure 访问 CouchDB API,Clojure 是一种面向 JVM 的动态语言。本文通过一些使用 Clutch API 和 clj-http 库的示例,分别展示一个高级 CouchDB API 和一些基于 REST 的低...

IBMdW
2011/06/22
804
1
Ubuntu 9.10 将集成CouchDB

Ubuntu 9.10已经正式完成了,不过开发者们正在尝试在新的beta版本中加入Apache CouchDB。Apache CouchDB可用于存储地址(addresses)、笔记(notes)和书签。 为什么会有这个近期的变更?究其...

红薯
2009/10/16
499
1

没有更多内容

加载失败,请刷新页面

加载更多

灵光一闪来个科普贴:Linux文件系统

在计算机系统中,各种需要保存的信息都是以文件的形式存在的。文件管理是对系统信息资源的管理,是操作系统的一项重要功能。 1.文件与文件系统: 1.1文件: 文件是具有名字的一组相关信息的有...

Linux就该这么学
24分钟前
3
0
ExtJS 4.2 评分组件

本文转载于:专业的前端网站➸ExtJS 4.2 评分组件 上一文章是扩展ExtJS自带的Date组件。在这里将创建一个评分组件。 目录 1. 介绍 2. 示例 3. 资源下载 1. 介绍 代码参考的是 Sencha Touch 2...

前端老手
28分钟前
3
0
如何为视频添加封面?

一个好的视频封面可以吸引观众的眼球,从而起到事半功倍的宣传效果,但是很多小伙伴并不知道怎么给视频添加封面。下面分享一个制作封面否方法,操作起来也比较简单的,有兴趣的小伙伴请接着往...

白米稀饭2019
38分钟前
3
0
如何使用soapUI模拟webservice客户端发送请求

参考资料 https://jingyan.baidu.com/article/cbcede0712849a02f40b4d88.html 左边是请求参数,可以自己填写!按着那个绿色三角箭头可以模拟发送请求,右边是返回的报文 soapui如何发送xml格...

故久呵呵
今天
6
0
Java Security 介绍

1.介绍 Java平台设计的重点是安全性。在其核心,java语言本身是类型安全的并且提供了垃圾自动回收,这使其增加了应用程序代码的健壮性。安全的类加载以及验证机制确保了只有合法的代码才能够...

lixiaobao
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部