设为首页 收藏本站
查看: 1414|回复: 0

[经验分享] 为什么PostgreSQL比MongoDB还快之续篇(WiredTiger引擎)

[复制链接]

尚未签到

发表于 2015-12-22 14:38:29 | 显示全部楼层 |阅读模式
今年的DTCC大会上,MongoDB中国的唐总带来了《如何在3.0实现7-10倍性能提升》。演讲时顺便倒了点苦水:一些其它数据库喜欢拿MongoDB进行性能PK,但MongoDB之前的开发一直没有怎么关注性能这块,以前也没有发布过官方的性能测试数据,所以结果可想而知。
但是,MongoDB 3.0带来了新的WiredTiger存储引擎,不再像以前(MMAPv1引擎)那样受制于OS内存映射,性能有7-10倍的提升。

这里有一份MongoDB的官方性能测试报告,根据这份测试报告,WiredTiger的性能提升主要表现在数据压缩和并行加载上。
http://www.mongoing.com/archives/862

由于WiredTiger不是默认引擎(根据唐总的说法,以后的版本会考虑作为默认引擎) 。我之前的那篇测试,对比的还是MongoDB的老引擎MMAPv1。
http://blog.iyunv.com/xmlrpc.php?r=blog/article&uid=20726500&id=4960138

下面用同样的测试方法看看WiredTiger引擎的表现(嫌测试过程写得太长的话,可以直接跳到后面看测试总结)。


1. MongoDB WiredTiger引擎的测试
1)启用MongoDB的WiredTiger引擎



  • -bash-4.1$ mongod --dbpath /data/db2 --storageEngine wiredTiger
  • 2015-04-18T07:51:26.647+0800 I STORAGE  [initandlisten] wiredtiger_open config: create,cache_size=1G,session_max=20000,eviction=(threads_max=4),statistics=(fast),log=(enabled=true,archive=true,path=journal,compressor=snappy),checkpoint=(wait=60,log_size=2GB),statistics_log=(wait=0),
  • 2015-04-18T07:51:27.561+0800 I CONTROL  [initandlisten] MongoDB starting : pid=21287 port=27017 dbpath=/data/db2 64-bit host=hanode1
  • 2015-04-18T07:51:27.563+0800 I CONTROL  [initandlisten] db version v3.0.2
  • 2015-04-18T07:51:27.563+0800 I CONTROL  [initandlisten] git version: 6201872043ecbbc0a4cc169b5482dcf385fc464f
  • 2015-04-18T07:51:27.564+0800 I CONTROL  [initandlisten] OpenSSL version: OpenSSL 1.0.1e-fips 11 Feb 2013
  • 2015-04-18T07:51:27.564+0800 I CONTROL  [initandlisten] build info: Linux ip-10-171-120-213 2.6.32-220.el6.x86_64 #1 SMP Wed Nov 9 08:03:13 EST 2011 x86_64 BOOST_LIB_VERSION=1_49
  • 2015-04-18T07:51:27.564+0800 I CONTROL  [initandlisten] allocator: tcmalloc
  • 2015-04-18T07:51:27.564+0800 I CONTROL  [initandlisten] options: { storage: { dbPath: "/data/db2", engine: "wiredTiger" } }
  • 2015-04-18T07:51:27.595+0800 I NETWORK  [initandlisten] waiting for connections on port 27017

2)加载数据





  • -bash-4.1$ time -p mongoimport --type json --collection json_tables --db benchmark /dev/null 2>/dev/null
  • real 8.53
  • user 7.99
  • sys 4.14

加载期间的系统负载



  • [iyunv@hanode1 ~]# top
  • top - 08:19:09 up 7 days, 11:19,  5 users,  load average: 0.48, 0.13, 0.04
  • Tasks: 151 total,   1 running, 150 sleeping,   0 stopped,   0 zombie
  • Cpu(s): 24.9%us,  9.3%sy,  0.0%ni, 56.8%id,  6.2%wa,  0.5%hi,  2.4%si,  0.0%st
  • Mem:   1019320k total,   949576k used,    69744k free,    82976k buffers
  • Swap:  2064376k total,    62092k used,  2002284k free,   215228k cached

  • PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
  • 24190 postgres  20   0  549m 219m 3312 S 114.7 22.1   0:08.94 mongoimport
  • 21287 postgres  20   0  634m 331m 4748 S 34.6 33.3   0:44.48 mongod
值得注意的是系统的瓶颈在mongoimport进程(mongoimport的CPU利用率超过了100%),而不是mongod进程mongod还有很多的余力

3)建索引



  • -bash-4.1$ echo "db.json_tables.ensureIndex( { \"name\": 1})" |time -p mongo benchmark >/dev/null

  • real 1.25
  • user 0.03
  • sys 0.03
  • -bash-4.1$ echo "db.json_tables.ensureIndex( { \"type\": 1})" |time -p mongo benchmark >/dev/null
  • real 0.45
  • user 0.02
  • sys 0.02
  • -bash-4.1$ echo "db.json_tables.ensureIndex( { \"brand\": 1})" |time -p mongo benchmark >/dev/null
  • real 0.37
  • user 0.05
  • sys 0.03

4)查看存储空间大小



  • -bash-4.1$ mongo benchmark

  • MongoDB shell version: 3.0.2
  • connecting to: benchmark
  • > db.json_tables.stats()
  • {
  •     "ns" : "benchmark.json_tables",
  •     "count" : 100001,
  •     "size" : 266284846,
  •     "avgObjSize" : 2662,
  •     "storageSize" : 43167744,
  •     "capped" : false,
  •     "wiredTiger" : {
  •         "metadata" : {
  •             "formatVersion" : 1
  •         },
  •         "creationString" : "allocation_size=4KB,app_metadata=(formatVersion=1),block_allocation=best,block_compressor=snappy,cache_resident=0,checkpoint=(WiredTigerCheckpoint.2=(addr=\"01e208e781e4d41e9d38e208e881e4369503e3e208e981e446480254808080e402928fc0e40291cfc0\",order=2,time=1429314987,size=43118592,write_gen=9063)),checkpoint_lsn=(2,40610048),checksum=uncompressed,collator=,columns=,dictionary=0,format=btree,huffman_key=,huffman_value=,id=5,internal_item_max=0,internal_key_max=0,internal_key_truncate=,internal_page_max=4KB,key_format=q,key_gap=10,leaf_item_max=0,leaf_key_max=0,leaf_page_max=32KB,leaf_value_max=1MB,memory_page_max=10m,os_cache_dirty_max=0,os_cache_max=0,prefix_compression=0,prefix_compression_min=4,split_deepen_min_child=0,split_deepen_per_child=0,split_pct=90,value_format=u,version=(major=1,minor=1)",
  •         "type" : "file",
  •         "uri" : "statistics:table:collection-2--333628209475642491",
  •         "LSM" : {
  •             "bloom filters in the LSM tree" : 0,
  •             "bloom filter false positives" : 0,
  •             "bloom filter hits" : 0,
  •             "bloom filter misses" : 0,
  •             "bloom filter pages evicted from cache" : 0,
  •             "bloom filter pages read into cache" : 0,
  •             "total size of bloom filters" : 0,
  •             "sleep for LSM checkpoint throttle" : 0,
  •             "chunks in the LSM tree" : 0,
  •             "highest merge generation in the LSM tree" : 0,
  •             "queries that could have benefited from a Bloom filter that did not exist" : 0,
  •             "sleep for LSM merge throttle" : 0
  •         },
  •         "block-manager" : {
  •             "file allocation unit size" : 4096,
  •             "blocks allocated" : 9066,
  •             "checkpoint size" : 43118592,
  •             "allocations requiring file extension" : 9046,
  •             "blocks freed" : 27,
  •             "file magic number" : 120897,
  •             "file major version number" : 1,
  •             "minor version number" : 0,
  •             "file bytes available for reuse" : 40960,
  •             "file size in bytes" : 43167744
  •         },
  •         "btree" : {
  •             "btree checkpoint generation" : 8,
  •             "column-store variable-size deleted values" : 0,
  •             "column-store fixed-size leaf pages" : 0,
  •             "column-store internal pages" : 0,
  •             "column-store variable-size leaf pages" : 0,
  •             "pages rewritten by compaction" : 0,
  •             "number of key/value pairs" : 0,
  •             "fixed-record size" : 0,
  •             "maximum tree depth" : 3,
  •             "maximum internal page key size" : 368,
  •             "maximum internal page size" : 4096,
  •             "maximum leaf page key size" : 3276,
  •             "maximum leaf page size" : 32768,
  •             "maximum leaf page value size" : 1048576,
  •             "overflow pages" : 0,
  •             "row-store internal pages" : 0,
  •             "row-store leaf pages" : 0
  •         },
  •         "cache" : {
  •             "bytes read into cache" : 267348602,
  •             "bytes written from cache" : 267938187,
  •             "checkpoint blocked page eviction" : 0,
  •             "unmodified pages evicted" : 0,
  •             "page split during eviction deepened the tree" : 0,
  •             "modified pages evicted" : 26,
  •             "data source pages selected for eviction unable to be evicted" : 3,
  •             "hazard pointer blocked page eviction" : 3,
  •             "internal pages evicted" : 0,
  •             "pages split during eviction" : 26,
  •             "in-memory page splits" : 6,
  •             "overflow values cached in memory" : 0,
  •             "pages read into cache" : 9005,
  •             "overflow pages read into cache" : 0,
  •             "pages written from cache" : 9063
  •         },
  •         "compression" : {
  •             "raw compression call failed, no additional data available" : 0,
  •             "raw compression call failed, additional data available" : 0,
  •             "raw compression call succeeded" : 0,
  •             "compressed pages read" : 9004,
  •             "compressed pages written" : 9020,
  •             "page written failed to compress" : 0,
  •             "page written was too small to compress" : 43
  •         },
  •         "cursor" : {
  •             "create calls" : 14,
  •             "insert calls" : 100001,
  •             "bulk-loaded cursor-insert calls" : 0,
  •             "cursor-insert key and value bytes inserted" : 266602485,
  •             "next calls" : 300006,
  •             "prev calls" : 1,
  •             "remove calls" : 0,
  •             "cursor-remove key bytes removed" : 0,
  •             "reset calls" : 100005,
  •             "search calls" : 0,
  •             "search near calls" : 0,
  •             "update calls" : 0,
  •             "cursor-update value bytes updated" : 0
  •         },
  •         "reconciliation" : {
  •             "dictionary matches" : 0,
  •             "internal page multi-block writes" : 2,
  •             "leaf page multi-block writes" : 28,
  •             "maximum blocks required for a page" : 345,
  •             "internal-page overflow keys" : 0,
  •             "leaf-page overflow keys" : 0,
  •             "overflow values written" : 0,
  •             "pages deleted" : 0,
  •             "page checksum matches" : 204,
  •             "page reconciliation calls" : 32,
  •             "page reconciliation calls for eviction" : 26,
  •             "leaf page key bytes discarded using prefix compression" : 0,
  •             "internal page key bytes discarded using suffix compression" : 9230
  •         },
  •         "session" : {
  •             "object compaction" : 0,
  •             "open cursor count" : 14
  •         },
  •         "transaction" : {
  •             "update conflicts" : 0
  •         }
  •     },
  •     "nindexes" : 4,
  •     "totalIndexSize" : 2826240,
  •     "indexSizes" : {
  •         "_id_" : 864256,
  •         "name_1" : 868352,
  •         "type_1" : 630784,
  •         "brand_1" : 462848
  •     },
  •     "ok" : 1
  • }
WiredTiger引擎的压缩效果确实不错,把253MB的原始数据压缩到了41MB。

5)数据查询
匹配9091条记录的查询:
点击(此处)折叠或打开


  • -bash-4.1$ echo "db.json_tables.find({ brand: 'ACME'}).count()"|mongo benchmark

  • MongoDB shell version: 3.0.2
  • connecting to: benchmark
  • 9091
  • bye
  • -bash-4.1$ echo "DBQuery.shellBatchSize = 10000000000;db.json_tables.find({ brand: 'ACME'})"|time -p mongo benchmark >/dev/null
  • real 3.93
  • user 3.56
  • sys 0.11
*)第1次测的时间是12秒,有IO等待的时间,上面是第2次测试的结果,即数据已经被缓存了。

看看top的资源占用。
点击(此处)折叠或打开


  • Tasks: 158 total,   2 running, 156 sleeping,   0 stopped,   0 zombie
  • Cpu(s): 22.6%us,  0.4%sy,  0.0%ni, 76.8%id,  0.0%wa,  0.0%hi,  0.2%si,  0.0%st
  • Mem:   1019320k total,   793584k used,   225736k free,    61424k buffers
  • Swap:  2064376k total,    64096k used,  2000280k free,   236052k cached

  • PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
  • 27969 postgres  20   0  752m  67m 9304 R 91.4 6.8   0:03.46 mongo
  • 26391 postgres  20   0  610m 325m  11m S 1.0 32.7   0:10.95 mongod
测试结果和MMAPv1引擎差不多,CPU把时间都耗在客户端的mongo进程上。因为客户端在处理大量输出结果时消耗了太多的资源。

为了排除大量数据处理的误导,下面执行一下0匹配的查询。



  • -bash-4.1$ echo "DBQuery.shellBatchSize = 10000000000;db.json_tables.find({ brand: 'ACME111'})"|time -p mongo benchmark >/dev/null

  • real 0.07
  • user 0.04
  • sys 0.01
测试结果MMAPv1引擎也差不多。

再试试0匹配的全表扫描。



  • -bash-4.1$ echo "db.json_tables.dropIndexes()"|mongo benchmark

  • MongoDB shell version: 3.0.2
  • connecting to: benchmark
  • {
  •     "nIndexesWas" : 4,
  •     "msg" : "non-_id indexes dropped for collection",
  •     "ok" : 1
  • }
  • bye
  • -bash-4.1$ echo "DBQuery.shellBatchSize = 10000000000;db.json_tables.find({ brand: 'ACME111'})"|time -p mongo benchmark >/dev/null
  • real 0.14
  • user 0.02
  • sys 0.03
测试结果MMAPv1引擎比快了有50%左右。


6)数据插入
先清数据


  点击(此处)折叠或打开


  • -bash-4.1$ echo "db.json_tables.drop()"|mongo benchmark
  • MongoDB shell version: 3.0.2
  • connecting to: benchmark
  • true
  • bye

插入数据



  • -bash-4.1$ time mongo benchmark --quiet /dev/null


  • real    1m31.420s
  • user    0m30.832s
  • sys    0m50.319s
测试结果也和MMAPv1引擎差不多。
并且由于MongoDB的控制台不允许插入大于4k的文档,最后插入的数据没有10万条。



  • -bash-4.1$ mongo benchmark

  • MongoDB shell version: 3.0.2
  • connecting to: benchmark
  • > db.json_tables.count()
  • 72728

下面看看插入时的系统负载



  • [iyunv@hanode1 ~]# top
  • top - 08:02:23 up 7 days, 11:02,  5 users,  load average: 0.00, 0.02, 0.00
  • Tasks: 154 total,   2 running, 152 sleeping,   0 stopped,   0 zombie
  • Cpu(s):  3.3%us,  1.5%sy,  0.0%ni, 76.4%id,  0.0%wa,  0.0%hi, 18.8%si,  0.0%st
  • Mem:   1019320k total,   888680k used,   130640k free,    83272k buffers
  • Swap:  2064376k total,    62140k used,  2002236k free,   295144k cached

  • PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
  • 22470 postgres  20   0  753m  66m 9224 R 88.8 6.7   0:03.94 mongo
  • 21287 postgres  20   0  634m 344m  11m S 22.3 34.6   0:12.53 mongod
这个测试结果也和MMAPv1引擎惊人的相识。那么WiredTiger引擎的插入性能提升在什么地方呢?
其实WiredTiger引擎在插入上主要提升的是并发性能,MMAPv1引擎在并发时是简单粗暴的锁库模式,严重制约并发性能,CPU核心再多性能也上不去。而我的测试是单并发测试,所以看不出MMAPv1引擎的这个致命缺点

2. 总结

以单并发时的服务端进程CPU消耗作为衡量指标,PG和WiredTiger的对比总结如下:
1)加载
  WiredTiger的性能是PG的3倍(注)
2)插入
相差不大,WiredTiger小胜(注
3)全表扫描(0匹配
WiredTiger的性能是PG的4倍
4)单点索引扫描(0匹配
PG的
性能是WiredTiger的4倍
5)数据大小

PG的数据大小是WiredTiger的3倍
DSC0000.png

注意,以上加载和插入的这两个数据以单并发时的服务端进程CPU消耗作为衡量指标的,忽略了MongoDB客户端的高CPU消耗,实际场景中也有可能PG更快。之所以这样对比,是因为:

我们假设好的引擎可以在高并发时可以把负载均衡地分散到所有CPU核心上
,对这样的引擎,在CPU成为瓶颈的场景中,单并发时的CPU实际占用时间可以作为一个重要的参考指标

但是,服务端能不能在高并发时实现多CPU核心上的线性或近似线性的性能Scale UP还需看服务端(PG/MongoDB)的素质和具体使用场景。

最后,即使PG在加载和插入的PK上输了也很正常,因为PG是保障了ACID的,WiredTiger却有丢失数据的风险。
Journal 默认不会即时刷盘,系统宕机会丢失最多100MB Journal数据










运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-154866-1-1.html 上篇帖子: MongoDB - MapReduce 实战 下篇帖子: ReactiveMongo Aggregation 聚合查询模型 -- MyEdu service ticket query
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表