Mongodb Mysql 小测试 (To Be Continued)

mongo-vs-mysql

尝试测试Mongodb 和 Mysql的性能,测试/数据导入代码:github: mongo-vs-mysql

性能比较很复杂,不能简单就说谁的性能高,谁的低。要基于场景,基于并发请求数量来谈,同时也要知道如何调优,本文只是初探,在没有任何调优的基础上,在本地windows 7上进行测试。

版本及环境

  • 操作系统: windows 7
  • 硬件环境: (只做对比,mongodb和mysql都装在同一台机器上)
  • mongodb: 3.2.5
  • mysql: 5.7

Data-demo

Data-demo 是一个Spring Boot的项目, 通过Spring Boot的CommandLineRunner来批量动态插入1000,020 条数据。

数据结构采用常用的产品和类目的多对多的设计。
这里写图片描述

Category 数据如下:
idcodename
‘1’‘cate-1’‘Category 1’
‘2’‘cate-2’‘Category 2’
‘3’‘cate-3’‘Category 3’
‘4’‘cate-4’‘Category 4’
Product 数据如下
idcodenameprice
‘1’‘p-0’‘product 0’‘19’
‘2’‘p-1’‘product 1’‘19’
‘3’‘p-2’‘product 2’‘19’
‘1000000’‘p-999999’‘product 999999’‘19’
‘1000001’‘pp-0’‘iphone’‘19’
‘1000002’‘pp-1’‘iphone’‘19’
‘1000003’‘pp-2’‘iphone’‘19’
‘1000004’‘pp-3’‘iphone’‘19’
‘1000005’‘pp-4’‘iphone’‘19’
‘1000006’‘pp-5’‘iphone’‘19’
‘1000007’‘pp-6’‘iphone’‘19’
‘1000008’‘pp-7’‘iphone’‘19’
‘1000009’‘pp-8’‘iphone’‘19’
‘1000010’‘pp-9’‘iphone’‘19’
‘1000011’‘pp-10’‘iphone’‘19’
‘1000012’‘pp-11’‘iphone’‘19’
‘1000013’‘pp-12’‘iphone’‘19’
‘1000014’‘pp-13’‘iphone’‘19’
‘1000015’‘pp-14’‘iphone’‘19’
‘1000016’‘pp-15’‘iphone’‘19’
‘1000017’‘pp-16’‘iphone’‘19’
‘1000018’‘pp-17’‘iphone’‘19’
‘1000019’‘pp-18’‘iphone’‘19’
‘1000020’‘pp-19’‘iphone’‘19’

最后的二十行是用来方便查询验证的。

Product_Category

中间mapping的表格

Mongo 数据

采用了 Nodejs+express+mongoose 来导入mongo的数据. 项目express-mongoose-microservice-api-boilerplate中的config/test.env来配置mongo的数据库地址。npm install 然后运行命令npm run produceTestData 可以初始化1000,020 条产品数据到mongodb。 数据类似mysql的产品数据:

产品 Product
{
    "_id": "59cb4952d44efa2eb45d4bf7",
    "code": "p-0",
    "name": "Product 0",
    "price": 19,
    "__v": 0,
    "categories": [
        "cate-1",
        "cate-2"
    ]
}

有20条产品数据的categories中有cate-4

通过查询脚本直接测试:

通过Robomongo 连接Mongodb来测试,通过mysql的workbench来完成mysql的脚本查询。

场景一:查询单个类目下的产品

mongo 查询所有的cate-4 的产品
db.getCollection('products').find({categories:'cate-4'}) // 初次查询1.321 秒 紧接着的两次查询大概0.791 秒
mysql 查询所有的cate-4 的产品
SELECT * FROM  product p inner join product_category pc inner join category c on p.id=pc.product_id and pc.category_id=c.id where c.code ='cate-4'; -- 毫秒级,时间可以忽略不计, 产品和类目的code都是unique的索引,所以查询速度很快
SELECT * FROM  product p inner join product_category pc inner join category c on p.id=pc.product_id and pc.category_id=c.id where c.name ='Category 4'; -- 6.2秒,name不是索引,所以慢。(索引的用处毫无疑问,无需赘述)

场景二:查询多个类目下的产品

查询所有cate-4 加上 cate-5 的产品。(实际上cate-5并不存在,不过不影响测试)

mongod
db.getCollection('products').find({categories:{$in:['cate-4','cate-5']}}) // 0.89 秒; 和查询cate-4的产品相差不多,都是全表扫描
mysql
SELECT * FROM  product p inner join product_category pc inner join category c on p.id = pc.product_id and pc.category_id = c.id where c.code = 'cate-5' or c.code='cate-4'; -- 6.177 秒,
SELECT * FROM  product p inner join product_category pc inner join category c on p.id = pc.product_id and pc.category_id = c.id where c.code in('cate-5','cate-4'); -- 6.24 秒

通过上面的测试可以看出,mysql数据库在数据体量大的时候,用or或者in都有很严重的性能问题,可以考虑使用union来代替。一般电商平台的处理方式:如果是后台维护功能应该从业务上来避免这种场景,如果是前端面向用户的功能,需要引入搜索引擎 比如: elasticsearch

场景三:单表无索引

查询名称是iphone的产品

Mysql
select * from product where name='iphone'; -- 0.546 秒,全表扫描
mongo
db.getCollection('products').find({name:'iphone'}) // 0.428 秒

全表扫描两者并无太大的差距。

场景四:单表索引

db.getCollection('products').find({code:'pp-1'})  
select * from product where code='pp-1';

一百万条数据,单表索引速度都是毫秒级,时间可以忽略不计。

场景五:单表索引字段使用In来查询

场景二我们提到了Mysql中关联表时使用in查询的效率问题。下面测试下单表的In查询效率, 通过测试我们可以发现单表针对索引的in的查询都是毫秒级的。
mongodb 历时0.004 sec. 索引被用上了

// 非ID的索引字段
db.getCollection('products').find({
    "code": {
        "$in": [
            "pp-0",
            "pp-1"
        ]
    }
})
// _id 主键的$in 查询
db.getCollection('products').find({
    "_id": {
        "$in": [
            ObjectId("59cb4952d44efa2eb45d4bf7"),
            ObjectId("59cb4952d44efa2eb45d4bf8")
        ]
    }
})

Mysql 也是毫秒级,时间忽略不计

select * from product where code in ('pp-0','pp-4'); // 0.0000 sec
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值