加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

为什么PostgreSQL比MongoDB还快?

发布时间:2020-12-13 17:15:47 所属栏目:百科 来源:网络整理
导读:PostgreSQL9.4带来了全新的NoSQL特性,并且根据EnterpriseDB的测试,其加载,插入和查询的性能都已经几倍于MongoDB了。 虽然我是PG的铁杆粉丝,但是关系数据库背负了ACID的重型装甲,在性能上居然能打败轻装上阵的NoSQL数据库总觉得有点离谱。 所以我在自己
PostgreSQL9.4带来了全新的NoSQL特性,并且根据EnterpriseDB的测试,其加载,插入和查询的性能都已经几倍于MongoDB了。
虽然我是PG的铁杆粉丝,但是关系数据库背负了ACID的重型装甲,在性能上居然能打败轻装上阵的NoSQL数据库总觉得有点离谱。
所以我在自己的环境里验证了一下EnterpriseDB的测试结果,并且小探一下PG取胜的原因。

1. EnterpriseDB的测试结果

以下是EnterpriseDB的测试结果(数据量为5000万)
http://www.enterprisedb.com/postgres-plus-edb-blog/marc-linster/postgres-outperforms-mongodb-and-ushers-new-developer-reality

(还可以参考这篇译文:http://blog.jobbole.com/78215/)
2.我的验证结果 测试观点
为了使测试结果更加单纯,我准备单纯比拼CPU消耗(尽量排除IO和网络的干扰),设定以下测试条件。
1)所有数据都要放进内存
2)C/S都跑在同一台 单机上
所以,只在单机上进行10万条小数据量的测试
注)EnterpriseDB的测试环境是32G内存的Amazon Web Services M3.2XLARGE实例,总数据量超过内存了。

测试环境
测试环境为个人PC上的VMware虚拟机
PC
CPU:Intel Core i5-3470 3.2G(4核)
MEM:6GB
SSD:OCZ-VERTEX4 128GB(VMware虚拟机所在磁盘,非系统盘)
OS:Win7
VMware虚拟机
CPU:4核
MEM:1GB
OS:CentOS 6.5
PG:PostgreSQL 9.4.0(shared_buffers = 428MB,其他是默认值)
MG: MongoDB 3.0.2
测试步骤
测试步骤非常简单,可以参考:
https://github.com/EnterpriseDB/pg_nosql_benchmark
但是,在测试前,有些东西要改。
1)把数据量减小到10万
pg_nosql_benchmark-master/pg_nosql_benchmark:
declare -a json_rows=(10000000)
==>
declare -a json_rows=(100000)
2)修改 mongo的 一处 脚本(注)
pg_nosql_benchmark-master/ lib/mongo_func_lib.sh:
collectionsize="$(echo ${output}|awk -F"," '{print $5}'|cut -d":" -f2)"
6 }'|cut -d":" -f2)"
) pg_nosql_benchmark原来是基于 2.6设计的,MongoDB3.0 的db.json_tables.stats()输出可能变了,所以这边要修改一下。
测试结果

点击(此处)折叠或打开

  1. -bash-4.1$ sh pg_nosql_benchmark
  2. PID: 2160 [RUNTIME: 04-12-15 08:15:51] pg_nosql_benchmark: MongoDB Version 3.0.2
  3. PID: 2160 [RUNTIME: 04-12-15 08:15:51] pg_nosql_benchmark: PostgreSQL Version 9.4.0
  4. PID: 2160 [RUNTIME: 04-12-15 08:15:51] pg_nosql_benchmark: creating json data.
  5. PID: 2160 [RUNTIME: 04-12-15 08:17:18] pg_nosql_benchmark: preparing postgresql INSERTs.
  6. PID: 2160 [RUNTIME: 04-12-15 08:19:02] pg_nosql_benchmark: preparing mongo insert commands.
  7. PID: 2160 [RUNTIME: 04-12-15 08:20:45] pg_nosql_benchmark: droping database benchmark if exists.
  8. PID: 2160 [RUNTIME: 04-12-15 08:20:45] pg_nosql_benchmark: creating database benchmark.
  9. PID: 2160 [RUNTIME: 04-12-15 08:20:46] pg_nosql_benchmark: dropping mongo collection json_tables
  10. PID: 2160 [RUNTIME: 04-12-15 08:20:46] pg_nosql_benchmark: creating json_tables collection in postgreSQL.
  11. PID: 2160 [RUNTIME: 04-12-15 08:20:46] pg_nosql_benchmark: loading data in postgresql using sample.json.
  12. PID: 2160 [RUNTIME: 04-12-15 08:20:57] pg_nosql_benchmark: creating index on postgreSQL collections.
  13. PID: 2160 [RUNTIME: 04-12-15 08:21:00] pg_nosql_benchmark: testing mongoimport.
  14. PID: 2160 [RUNTIME: 04-12-15 08:21:14] pg_nosql_benchmark: creating index in mongodb.
  15. PID: 2160 [RUNTIME: 04-12-15 08:21:19] pg_nosql_benchmark: testing FIRST SELECT in postgresql.
  16. PID: 2160 [RUNTIME: 04-12-15 08:21:21] pg_nosql_benchmark: testing SECOND SELECT in postgresql.
  17. PID: 2160 [RUNTIME: 04-12-15 08:21:22] pg_nosql_benchmark: testing THIRD SELECT in postgresql.
  18. PID: 2160 [RUNTIME: 04-12-15 08:21:22] pg_nosql_benchmark: testing FOURTH SELECT in postgresql.
  19. PID: 2160 [RUNTIME: 04-12-15 08:21:23] pg_nosql_benchmark: calculating PostgreSQL collection size.
  20. PID: 2160 [RUNTIME: 04-12-15 08:21:23] pg_nosql_benchmark: testing mongo FIRST SELECT.
  21. PID: 2160 [RUNTIME: 04-12-15 08:21:27] pg_nosql_benchmark: testing mongo SECOND SELECT.
  22. PID: 2160 [RUNTIME: 04-12-15 08:21:27] pg_nosql_benchmark: testing mongo THIRD SELECT.
  23. PID: 2160 [RUNTIME: 04-12-15 08:21:30] pg_nosql_benchmark: testing mongo FOURTH SELECT.
  24. PID: 2160 [RUNTIME: 04-12-15 08:21:33] pg_nosql_benchmark: calculating the size of mongo collection.
  25. PID: 2160 [RUNTIME: 04-12-15 08:21:34] pg_nosql_benchmark: dropping mongo collection json_tables
  26. PID: 2160 [RUNTIME: 04-12-15 08:21:34] pg_nosql_benchmark: testing inserts in mongo
  27. PID: 2160 [RUNTIME: 04-12-15 08:23:00] pg_nosql_benchmark: droping json object in postgresql.
  28. PID: 2160 [RUNTIME: 04-12-15 08:23:00] pg_nosql_benchmark: inserting data in postgresql using sample_pg_inserts.json.
  29. number of rows 100000
  30. PG COPY (ns) 10886811763
  31. PG INSERT (ns) 22173081221
  32. PG SELECT (ns) 1018231815
  33. PG SIZE (bytes) 148946944
  34. MONGO IMPORT (ns) 13880183843
  35. MONGO INSERT (ns) 86577229486
  36. MONGO SELECT (ns) 2669842035
  37. MONGO SIZE (bytes) 429092864
除了数据加载的性能差距不明显外,其它数据基本和 EnterpriseDB的测试结果一致(MongoDB 插入时间是PG的4倍,查询时间 是PG的2倍多)。
3. PostgreSQL真的比MongoDB还快吗
下面模仿 EnterpriseDB的测试方法,单独进行每一项测试。

3.1 测试数据

修改测试脚本后再次执行,将加载和插入的数据文件保留下来。
pg_nosql_benchmark:

点击(此处)折叠或打开

  • rm -rf ${SAMPLEJSON}*
  • rm -rf ${PG_INSERTS}
  • rm -rf ${MONGO_INSERTS}
  • 点击(此处)折叠或打开

  • #rm -rf ${SAMPLEJSON}*
  • #rm -rf ${PG_INSERTS}
  • #rm -rf ${MONGO_INSERTS}

  • 查看一下数据

    点击( 此处 )折叠或打开
  • -bash-4.1$ head -1 sample.json
  • { "name" : "AC33929 Phone","brand" : "ACME1415","type" : "phone","price" : 200,"warranty_years" : 1,"available" : true,"description": "Lorem ipsum dolor sit amet,consectetur adipiscing elit. Proin eget elit ut nulla tempor viverra vel eu nulla. Sed luctus porttitor urna,ac dapibus velit fringilla et. Donec iaculis,dolor a vehicula dictum,augue neque suscipit augue,nec mollis massa neque in libero. Donec sed dapibus magna. Pellentesque at condimentum dolor. In nunc nibh,dignissim in risus a,blandit tincidunt velit. Vestibulum rutrum tempus sem eget tempus. Mauris sollicitudin purus auctor dolor vestibulum,vitae pulvinar neque suscipit. Cum sociis natoque penatibus et magnis dis parturient montes,nascetur ridiculus mus. Phasellus lacus turpis,vulputate at adipiscing viverra,ultricies at lectus. Pellentesque ut porta leo,vel eleifend neque. Nunc sagittis metus at ante pellentesque,ut condimentum libero semper. In hac habitasse platea dictumst. In dapibus posuere posuere. Fusce vulputate augue eget tellus molestie,vitae egestas ante malesuada. Phasellus nunc mi,faucibus at elementum pharetra,aliquet a enim. In purus est,vulputate in nibh quis,faucibus dapibus magna. In accumsan libero velit,eu accumsan sem commodo id. In fringilla tempor augue,et feugiat erat convallis et. Sed aliquet eget ipsum eu vestibulum.Curabitur blandit leo nec condimentum semper. Mauris lectus sapien,rutrum a tincidunt id,euismod ac elit. Mauris suscipit et arcu et auctor. Quisque mollis magna vel mi viverra rutrum. Nulla non pretium magna. Cras sed tortor non tellus rutrum gravida eu at odio. Aliquam cursus fermentum erat,nec ullamcorper sem gravida sit amet. Donec viverra,erat vel ornare pulvinar,est ipsum accumsan massa,eu tristique lorem ante nec tortor. Sed suscipit iaculis faucibus. Maecenas a suscipit ligula,vitae faucibus turpis.Cras sed tellus auctor,tempor leo eu,molestie leo. Suspendisse ipsum tellus,egestas et ultricies eu,tempus a arcu. Cras laoreet,est dapibus consequat varius,nisi nisi placerat leo,et dictum ante tortor vitae est. Duis eu urna ac felis ullamcorper rutrum. Quisque iaculis,enim eget sodales vehicula,magna orci dignissim eros,nec volutpat massa urna in elit. In interdum pellentesque risus,feugiat pulvinar odio eleifend sit amet. Quisque congue libero quis dolor faucibus,a mollis nisl tempus." }

  • 查看 数据的总大小,10万条记录共 253MB。
  • -bash-4.1$ ls -l *.json
  • -rw-r--r-- 1 postgres postgres 264993924 Apr 12 08:17 sample.json
  • -rw-r--r-- 1 postgres postgres 267493911 Apr 12 08:20 sample_mongo_inserts.json
  • -rw-r--r-- 1 postgres postgres 269493962 Apr 12 08:19 sample_pg_inserts.json

  • 3.2 PostgreSQL测试

    1)清理旧数据

    点击(此处)折叠或打开

  • benchmark=#droptablejson_tables;
  • DROPTABLE
  • benchmarkcreate(datajsonb);
  • CREATETABLE

  • 2)加载数据

    点击(此处)折叠或打开

  • -bash-4.1$ cat sample.json |time -p psql benchmark -c "copy json_tables from stdin;"
  • real 10.00
  • user 0.00
  • sys 0.35

  • 执行测试期间的系统负载

    点击(此处)折叠或打开

  • [root@hanode1 ~]# top
  • top - 09:12:31 up 1 day,12:12,5 users,load average: 0.15,0.03,0.01
  • Tasks: 160 total,2 running,158 sleeping,0 stopped,0 zombie
    Cpu(s): 14.3%us,13.3%sy,0.0%ni,70.0%id,1.9%wa,0.1%hi,0.4%si,0.0%st
    Mem: 1019320k total,942632k used,76688k free,9768k buffers
    Swap: 2064376k total,80232k used,1984144k free,840444k cached

    PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
    30622 postgres 20 0 588m 34m 32m R93.43.5 0:08.00 postgres
    30619 postgres 20 0 98.6m 568 464 S 13.3 0.1 0:00.99 cat
    17197 postgres 20 0 587m 212m 211m S 10.3 21.3 0:05.91 postgres
    17199 postgres 20 0 586m 14m 13m S 5.0 1.4 0:03.26 postgres
    30621 postgres 20 0 167m 2496 1984 S 3.3 0.2 0:00.30 psql
    22 root 20 0 0 0 0 S 0.3 0.0 1:13.42 events/3
    35 root 20 0 0 0 0 S 0.3 0.0 0:01.84 kblock
  • 注意红色的部分,postgres进程的CPU利用率接近了极限。
    3) 建索引
  • -bash-4.1$ time -p psql benchmark -c "create index json_tables_idx on json_tables using gin(data);"
  • CREATE INDEX
  • real 2.71
  • user 0.00
  • sys 0.00

  • 4)查看存储空间大小

    点击(此处)折叠或打开

    1. selectpg_relation_size('json_tables';
    2. pg_relation_size
    3. ------------------
    4. 148946944
    5. (1row)

    6. benchmark'json_tables_idx';
    7. pg_relation_size
    8. ------------------
    9. 51134464
    10. )
    PostgreSQL的jsonb存储优化还是不错的,表占了142MB,比原始数据( 253MB)要小。

    5)数据查询
    点击( 此处 )折叠或打开
    -bash-4.1$ time psql-qAt benchmark-c"SELECT data FROM json_tables WHERE (data->>'brand') = 'ACME';">/dev/null

  • real0m0.784s
  • user0m0.044s
  • sys0m0.032s

  • 看看执行计划

    点击(此处)折叠或打开

    #explain(analyze,buffersSELECTdataFROMjson_tablesWHERE->'brand'='ACME';
  • QUERY PLAN
  • -------------------------------------------------------------------------------------------------------------------
  • Seq Scanonjson_tables(cost=0.00..19682.01rows=500 width=1262(actual time.192.486.710=9091 loops=1)
  • Filter::text)
  • RowsRemovedbyFilter:90910
  • Buffers:shared hit=2304 read=15878
  • Planning time:0.645 ms
  • Execution time:487.951 ms
  • (6)

  • 居然是顺序扫描!GIN索引是吃干饭的吗?
    仔细一看,原来 EnterpriseDB的测试SQL里把操作符写错了,无法使用GIN索引(想不到PG大牛出没的 EnterpriseDB也会犯这么低级的错误)。下面改下SQL让GIN上场。

    点击(此处)折叠或打开

    @'{"brand":"ACME"}'------------------------------------------------------------------------------------------------------------------------------
  • Bitmap Heap Scan=28.78.407=100 width=3.612.47.001)
  • Recheck Cond'{"brand": "ACME"}':jsonb)
  • Heap Blocks:exact=9091
  • Buffers=9110
  • >BitmapIndexScanonjson_tables_idx.28.75=2.162.2IndexCond)
  • Buffers=19
  • Planning time.175 ms
  • Execution time:47.690 ms
  • (9)
  • 效果好了不少啊!

    换到外面用psql测。
    点击( 此处 )折叠或打开
    "SELECT data FROM json_tables WHERE data @> '{"brand":"ACME"}'".326s
  • .047s
  • sys0m0.031s

  • 比以前有数据时快了1倍,但是没有explain (analyze,buffers)快。原因也很简单,输出结果太多了, 9091条数据在客户端和服务端都要消耗不少资源,而explain (analyze,buffers) 只是简单的在服务端把结果丢弃

    为了排除 处理大量结果数据的干扰,换一个0匹配的查询再试试。
    点击( 此处 )折叠或打开
    ":"ACME111.015s
  • .005s
  • sys0m0.002s
  • 15ms,简直神速啊!

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

    点击(此处)折叠或打开

    "set enable_bitmapscan=false;SELECT data FROM json_tables WHERE data @> '{"brand"}'"

  • .594s
  • .002s
  • sys0m0.006s
  • 全表扫描明显慢多了。

    6)数据插入
    先清数据

    点击(此处)折叠或打开

    truncatejson_tables;
  • TRUNCATETABLE

  • 插入数据

    点击(此处)折叠或打开

    .1$ time-p psql-qAt benchmark--single-transaction -f sample_pg_inserts.json
  • real20.77
  • user1.23
  • sys 2.80

  • 插入期间的系统负载

    点击(此处)折叠或打开

  • [root@hanode1 ~]# top
    top - 09:58:31 up 1 day,12:58,load average: 0.23,0.05,0.02
    Tasks: 161 total,3 running,0 zombie
    Cpu(s): 17.0%us,8.0%sy,71.7%id,3.0%wa,0.0%hi,0.3%si,936824k used,82496k free,11420k buffers
    Swap: 2064376k total,80128k used,1984248k free,833644k cached

    PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
    2891 postgres 20 0 587m 110m 109m R74.511.1 0:07.45 postgres
    2890 postgres 20 0 167m 2600 2044 R19.60.3 0:01.87 psql
    17197 postgres 20 0 587m 212m 211m S 3.3 21.3 0:06.55 postgres
    17199 postgres 20 0 586m 14m 13m S 3.0 1.4 0:03.54 postgres
    17198 postgres 20 0 586m 2648 2512 S 0.3 0.3 0:01.09 postgres
    25933 root 20 0 15036 1088 804 R 0.3 0.1 3:01.30 top
    1 root 20 0 19356 816 648 S 0.0 0.1 0:01.18 init
  • postgres进程的CPU利用率达到74.5%。
    postgres进程的 CPU利用率为什么还要空这么多?原因也很简单,客户端和服务端是串行处理的,在空闲的时间里,它在等psql。
    那么把postgres的psql进程的CPU利用率加起来就是94.1%,确实可以判断达CPU性能瓶颈了。


    等一等!其实这个测试中PG作弊了。
    既然是和MongoDB PK普通的插入操作,应该是一个SQL一个事务才对。修改后再测。

    点击(此处)折叠或打开

    -f sample_pg_inserts.json
  • real43.64
  • user0.80
  • sys 2.89

  • 查看系统负载。

    点击(此处)折叠或打开

  • [root@hanode1 ~]# top
    top - 11:33:20 up 1 day,14:33,load average: 0.22,0.02
    Tasks: 157 total,155 sleeping,0 zombie
    Cpu(s): 2.1%us,14.1%sy,10.2%wa,1.8%si,947744k used,71576k free,8044k buffers
    Swap: 2064376k total,67764k used,1996612k free,846260k cached

    PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
    12577 postgres 20 0 587m 89m 88m D52.99.0 0:08.94 postgres
    12576 postgres 20 0 167m 2596 2040 S 8.60.3 0:01.35 psql
    12135 postgres 20 0 586m 48m 47m S 3.0 4.9 0:00.11 postgres
    34 root 20 0 0 0 0 S 1.0 0.0 0:02.83 kblockd/0
    36 root 20 0 0 0 0 S 0.3 0.0 0:02.63 kblockd/2
    59 root 20 0 0 0 0 R 0.3 0.0 0:11.01 kswapd0
  • 这次 执行时间也长了1倍,postgres+psql进程的CPU也没用满,才61.5%。CPU的空闲那段时间应该是在等WAL被 刷到磁盘
    (由于这是单并发测试,不可避免会出现CPU空闲;但是在多并发的环境里,只要存储的吞吐和IOPS足够高,是完全可以把CPU撑满的。)

    3.3MongoDB

    1)清理旧数据
    点击( 此处 )折叠或打开
    >db.json_tables.drop)
  • true

  • 2)加载数据

    点击(此处)折叠或打开

    -p mongoimport-typejson-collection json_tables-db benchmark<sample.jsonnull2null
  • real 10.22
  • user 7.44
  • sys 5.15

  • 加载期间的系统负载

    点击(此处)折叠或打开

  • [root@hanode1 ~]# top
    top - 10:15:50 up 1 day,13:15,load average: 0.16,0.01
    Tasks: 152 total,1 running,151 sleeping,0 zombie
    Cpu(s): 17.4%us,18.7%sy,57.8%id,5.3%wa,0.2%hi,0.5%si,895156k used,124164k free,1532k buffers
    Swap: 2064376k total,65560k used,1998816k free,428380k cached

    PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
    4673 postgres 20 0 694m 222m 3436 S89.822.4 0:05.53 mongoimport
    4015 postgres 20 0 2771m 290m 142m S49.529.2 0:04.29 mongod
  • 值得注意的是系统的瓶颈在mongoimport 进程,而不是mongod进程 mongod还有一半的余力
    (数据加载时,执行的单条语句,大量数据,所以 mongoimport 和mongod进程不是串行而是并行执行的关系

    3)建索引

    点击(此处)折叠或打开

    .1$echo"db.json_tables.ensureIndex( { "name": 1})"|time-p mongo benchmarknull
  • real 1.35
  • user 0.03
  • sys 0.02
  • "db.json_tables.ensureIndex( { "type": 1})"null
  • real 0.58
  • user 0.07
  • sys 0.01
  • "db.json_tables.ensureIndex( { "brand": 1})".50
  • user 0.01
  • MongoDB建的是btree索引,json中的每个常用的查询属性都要建1个,万一漏了就只能全集合扫描了(在一个无模式的数据模型里却需要建有模式的索引,不是有点讽刺吗?) 而PostgreSQL的GIN索引确是对整个json建的索引。这样一比较,PostgreSQL的GIN索引简直太牛了(不光 MongoDB,其它数据库也难有能和PG的扩展索引(GIN,GiST,SP-GiST)匹敌的东西吧?)。

    4)查看存储空间大小
    .stats{
  • "ns":"benchmark.json_tables"
  • "count":100001"size"419640560"avgObjSize":4196"numExtents":16"storageSize"429092864"lastExtentSize":114012160"paddingFactor":1"paddingFactorNote""paddingFactor is unused and unmaintained in 3.0. It remains hard coded to 1.0 for compatibility only.""userFlags""capped":false"nindexes":4"totalIndexSize":12452048"indexSizes""_id_":3262224"name_1":3899952"type_1":3442096"brand_1":1847776
  • }"ok":1
  • }
  • MongoDB的json存储 比原始数据( 253MB )稍微大一点,409MB。但是这个409MB是包含预先分配了但还没有使用的空间的,不考虑这部分空间则占了400MB(MongoDB每次扩张的空间量会越来越大,所以有时候单看storageSize不是很精确)。

    5)数据查询
    点击( 此处 )折叠或打开
    "DBQuery.shellBatchSize = 10000000000;db.json_tables.find({ brand: 'ACME'})"null
  • real 3.62
  • user 3.53
  • sys 0.09
  • 查询时间确实长了,比PG慢太多。

    但是,不要急,看看资源占用。

    点击(此处)折叠或打开

  • [root@hanode1 ~]# top
    top - 10:55:46 up 1 day,13:55,load average: 0.13,0.04,150 sleeping,0 zombie
    Cpu(s): 24.7%us,0.4%sy,74.8%id,0.0%wa,0.1%si,935684k used,83636k free,1464k buffers
    Swap: 2064376k total,66976k used,1997400k free,615840k cached

    PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
    8773 postgres 20 0 752m 67m 9052 R100.46.8 0:03.20 mongo
    4015 postgres 20 0 2803m 830m 663m S 0.7 83.4 0:26.46 mongod
    1424 root -2 0 85108 1448 1256 S 0.3 0.1 0:19.60 lrmd
    1425 hacluste -2 0 89600 1496 1208 S 0.3 0.1 0:25.34 attrd
    25911 root 20 0 98.0m 1104 972 S 0.3 0.1 0:40.12 sshd
    1 root 20 0 19356 812 660 S 0.0 0.1 0:01.19 init
  • 看到没,时间都耗在客户端的mongo进程上。因为客户端在处理大量输出结果时消耗了太多的资源。
    其实,执行psql时如果不加“-A”选项也会有类似的问题。

    点击(此处)折叠或打开

    -qt-p 5433 benchmarkreal0m2.124s
  • user0m1.401s
  • sys0m0.066s

  • 这说明什么?说明之前的查询测试结果根本就是误导嘛!(这就好比两个绝顶高手决斗的时候,比拼的却是谁的小弟递枪的速度快。)
    为了排除大量数据处理的误导,下面执行一下0匹配的查询。

    点击(此处)折叠或打开

    "DBQuery.shellBatchSize = 10000000000;db.json_tables.find({ brand: 'ACME111'})"null
  • real 0.06
  • user 0.01
  • 现在快多了。但是比起PostgreSQL执行相同查询的0.015s还是慢了很多。

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

    点击(此处)折叠或打开

    "db.json_tables.dropIndexes()"|mongo benchmark
  • MongoDB shellversion:3.0.2
  • connectingto:benchmark
  • "nIndexesWas""msg""non-_id indexes dropped for collection"}
  • .24
  • user 0.02
  • MongoDB的全表扫描比PostgreSQL快, PostgreSQL在相同条件下的执行时间是0.594s

    6)数据插入
    先清数据

    点击(此处)折叠或打开

    "db.json_tables.drop()"true
  • bye

  • 插入数据

    点击(此处)折叠或打开

    .1$ time mongo benchmark-quiet<sample_mongo_insertsnull

  • real1m27.591s
  • user0m29.663s
  • sys0m48.646s
  • MongoDB的插入确实挺慢的。
    而且如果查看输出的话,还会发现一堆错误,这是由于MongoDB的控制台不允许插入大于4k的文档。

    点击(此处)折叠或打开

  • 2015-04-12T11:19:08.680+0800 E QUERY SyntaxError: Unexpected token ILLEGAL
  • 2015-04-12T11:19:08.681+0800 E QUERY SyntaxError: Unexpected identifier
  • WriteResult({ "nInserted" : 1 })
  • WriteResult({ "nInserted" : 1 })
  • WriteResult({ "nInserted" : 1 })

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

    点击(此处)折叠或打开

  • [root@hanode1 ~]# top
    top - 11:20:26 up 1 day,14:20,load average: 0.00,0.00,0.00
    Tasks: 151 total,149 sleeping,0 zombie
    Cpu(s): 3.3%us,1.9%sy,71.1%id,4.9%wa,18.7%si,948452k used,70868k free,4076k buffers
    Swap: 2064376k total,68296k used,1996080k free,632796k cached

    PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
    11269 postgres 20 0 753m 66m 9224 R89.66.7 0:15.23 mongo
    4015 postgres 20 0 2803m 534m 371m S22.653.7 0:38.06 mongod
  • 根据 系统负载,性能瓶颈还是客户端mongo进程。如果要把mongod的负载压满, MongoDB的性能还可以提升4倍。

    4. 总结

    测试数据总结如下(并根据服务端进程CPU的消耗量进行性能对比):
    PostgreSQL MongoDB PK结果
    测试数据 务端进程
    CPU利用率

    CPU占用
    时间
    测试数据 服务
    CPU利用率

    CPU占用
    时间
    Data Load(s) 10 93.40% 9.34 10.22 49.50% 5.06 MongoDB胜出(*1)
    Insert(s) 20.77 74.50% 15.47 - - - 不具可比性
    每SQL事Insert(s) 43.64 52.90% 23.09 87.591 22.60% 19.80 MongoDB
    全表描Select(s) 0.784 - - - - - 不具可比性
    Select(s) 0.326 - - 3.62 0.70% 0.03 不具可比性
    0匹配Select(s) 0.015 - - 0.06 - - PostgreSQL
    0匹配全表描Select(s) 0.594 - - 0.24 - - 不具可比性
    Size(MB) 142 - - 409 - - PostgreSQL
    索引Size(MB) 49 - - 9(*2) - - 不具可比性
    *1)考虑到数据加载经常是单线程操作,不能完全无视mongoimport的瓶颈,这一局应该算是平手。
    *2)3个索引的总Size(MB)

    这个结果和 EnterpriseDB的测试结果有很大出入。
    1)数据加载
    从服务端资源消耗的角度看,是 MongoDB的性能是 PostgreSQL的2倍。但是如果数据加载不能很好的并发展开,让mongoimport成为了瓶颈,那应该算打平。
    另外, EnterpriseDB的 数据加载的测试结果和我的结果差异比较大,可能是因为EnterpriseDB的测试中,数据量超过了系统内存量,IO对测试结果的影响开始显现。

    2)数据插入
    服务端 资源消耗 的角度看,两者其实相差不大。EnterpriseDB的测试结果被mongo客户端的性能瓶颈绑架了。

    3)数据查询
    对无匹配数据(或少量匹配数据)的索引查询, PostgreSQL的性能是MongoDB的4倍(这一点也有点令人不解,同样是走索引的单点查询,为什么差距就这么大呢?)。
    虽然EnterpriseDB的测试结果也表明PostgreSQL的性能MongoDB 4倍左右,但EnterpriseDB的测试方法是有问题的。

    4)数据大小
    MongoDB的数据大小大约是 PostgreSQL的3倍,这和 EnterpriseDB的测试结果是一致的。

    PostgreSQL在NoSQL方面的表现确实抢眼。 PostgreSQL不仅是SQL+NoSQL+ACID的完美组合,性能还比 MongoDB技高一筹(分布式集群上MongoDB更有优势)

    6. 参考

    http://www.enterprisedb.com/postgres-plus-edb-blog/marc-linster/edb-makes-open-call-postgres-nosql-performance-benchmarks http://blog.163.com/digoal@126/blog/static/16387704020151443228780/ http://blog.163.com/digoal@126/blog/static/16387704020151435825593/ http://blog.163.com/digoal@126/blog/static/1638770402015142858224/ http://www.cnblogs.com/lovecindywang/archive/2011/03/02/1969324.html

    (编辑:李大同)

    【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

      推荐文章
        热点阅读