• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • MsSql
  • Mysql
  • oracle
  • MariaDB
  • DB2
  • SQLite
  • PostgreSQL
  • MongoDB
  • Redis
  • Access
  • 数据库其它
  • sybase
  • HBase
您的位置:首页 > 数据库 >MongoDB > MongoDB数据库查询性能提高40倍的经历分享

MongoDB数据库查询性能提高40倍的经历分享

作者:mydeman 字体:[增加 减小] 来源:互联网 时间:2017-05-11

mydeman通过本文主要向大家介绍了mongodb数据库,mongodb数据库设计,mongodb数据库下载,mongodb数据库教程,mongodb数据库文件等相关知识,希望本文的分享对您有所帮助

前言

数据库性能对软件整体性能有着至关重要的影响,本文给大家分享了一次MongoDB数据库查询性能提高40倍的经历,感兴趣的朋友们可以参考学习。

背景说明

1、数据库:MongoDB

2、数据集:

  • A:字段数不定,这里主要用到的两个UID和Date
  • B:三个字段,UID、Date、Actions。其中Actions字段是包含260元素JSON数组,每个JSON对象有6个字段。共有数据800万条左右。

3、业务场景:求平均数

  • 通过组合条件从A数据表查询出(UID,Date)列表,最多可能包含数万条记录;
  • 然后用第1步的结果从B中查询出对应的数据
  • 用第2步结果去Actions的某个固定位置的元素的进行计算

进化过程

在这里使用Python演示

最直接想到的方法

根据上面的业务场景描述,最容易想到的解决方法就是

from pymongo import MongoClient
# 连接数据库
db = MongoClient('mongodb://127.0.0.1:27017')['my_db']

# 简化的查询数据集A的条件
filter = {...}
# 查询Collection A
a_cursor = db.a.find(_filter)
a_docs = [x for x in a_cursor]

# 变量的初始定义
count = 0
total = 0
# 加入需要用到的元素为第21个
index = 20
# 查询Collection B,同时做累加
for a_doc in a _docs:
 b_doc = db.b.find_one({'uid':a_doc['uid'], 'date': a_doc['date']})
 # 只有能查到相应的结果时,才可以
 if b_doc is not None:
 total += b_doc['actions'][20]['number']
 count += 1

 # 求平均数
 if count > 0 :
 avg = total/count
</div>

实现难度当然是最低的,可是整个任务在第一步只有1万条左右的返回时,消耗的时间竟然达到了惊人38秒。当然这是已经加了索引的结果,否则可能都无法得到结果了。

减少查询次数

瓶颈显而易见,在循环中查询Collection B,增加了网络开销,自然也就增加时间,如果一次查询出所有结果,自然会大大提高效率。也就是说,我要把第一步的结果作为条件一次性传递,做一个$in操作。可是怎么才能做到呢?如果在uid和date上分别做$in操作,那么返回的结果就会是二者单独做$操作的合集,很显然这和要求是不符的。

经过上面的分析,似乎进入了死胡同。其实答案也基本显现了,需要有一个字段可以满足上面的要求,那么这个字段就是uid和date的合体,就命名为uid_date。uid_date是一个新字段,在B中并不存在,在使用之前需要将数据库现有的数据做一下处理。

处理完毕改造程序:

# 下面的只体现和本次修改相关的内容
uid_date_list = []
for a_doc in a_docs:
 uid_date_list.append(a_doc['uid'] + '_' + a_doc['date'])

# 查询B
b_cursor = db.b.find({'uid_date':{'$in':uid_date_list}})

# 下面就是取出结果,求平均数
...
</div>

这一番改造颇费时间,主要是前期的数据处理。代码改造完毕,执行下看看吧。

可是,可是…… 45秒

我做错了什么?!

增加返回记录数

我还是坚信上面的优化思路是对的,现在看看数据库能给一些什么线索吧。

登录到数据库服务器,找到MongoDB的日志/data/mongodb/logs/mongod.log。仔细查找,发现在查询数据集B时有很多getMore命令。这就奇怪了,我是一次性查询,为什么还有getMore。

赶紧查下官方的文档,然后发现了下面的内容:


batcSize参数指定了每次返回的个数,默认的101个。那看来这个应该是问题所在。找下pymongo的文档,也可以设置这个参数,那就设个大的吧10000。

再次改造程序如下:

# 增加batch_size
b_cursor = db.b.find({'uid_date':{'$in': uid_date_list}}, batch_size=10000)
</div>

这次总该可以了。

嗯,好了一些,降到了20秒左右。可是,这离1秒只能还差距20倍呢。

返回值减负

当日不能放弃,继续通过日志查找线索,发现还是有很多getMore。通过各方查找,发现mongodb每次最多返回16M的记录,通过getMore日志的比对,发现的确如此。由于B中每条记录的过去庞大,每次只能几百条记录,因此要一次多返回,那就必须要减少每次返回的记录数。因为在计算时,只用了特定索引位置上的数据,所以只返回该条记录就可以了。

最后的代码就不再写了,具体可以参考官方文档的实例。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

</div>
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • MongoDB的基础知识简介
  • mongodb在建立一个T级别的数据库时,进程挂掉的解决方法
  • MongoDB数据库查询性能提高40倍的经历分享
  • MongoDB在不同主机间复制数据库和集合的教程
  • 浅谈MongoDB的备份方式
  • MongoDB中的MapReduce简介
  • MongoDB简介 MongoDB五大特色
  • MongoDB数据库的特色和优点介绍
  • MongoDB导出查询结果到文件例子
  • Mongodb数据库的备份与恢复操作实例

相关文章

  • 2017-05-11MongoDB的安装方法图文教程
  • 2017-05-11MongoDB分片测试
  • 2017-05-11Centos 7下Mongodb开机无法自启动的解决方法
  • 2017-05-11Mongodb批量删除gridfs文件实例
  • 2017-05-11MongoDB的安装及配置文件选项全解
  • 2017-05-11MongoDB的一些常用查询方法
  • 2017-05-11MongoDB中创建索引需要注意的事项
  • 2017-05-11MongoDB的聚合框架Aggregation Framework入门学习教程
  • 2017-05-11在Linux ubuntu下安装mongodb的方法
  • 2017-05-11centos7防火墙导致java程序访问mongodb3.0.1时报错的问题分析

文章分类

  • MsSql
  • Mysql
  • oracle
  • MariaDB
  • DB2
  • SQLite
  • PostgreSQL
  • MongoDB
  • Redis
  • Access
  • 数据库其它
  • sybase
  • HBase

最近更新的内容

    • MongoDB与MySQL的操作对比表及区别介绍
    • mongodb使用心得简单总结
    • MongoDB系列教程(三):Windows中下载和安装MongoDB
    • mongodb 命令行下及php中insert数据详解
    • Mongodb 数据类型及Mongoose常用CURD
    • mongodb 实现远程连接
    • MongoDB入门教程之细说MongoDB数据库的增删查改操作
    • Mongodb常见错误与解决方法小结(Mongodb中经常出现的错误)
    • window平台安装MongoDB数据库图文详解
    • MongoDB中的主从同步配置和mongod相关启动命令讲解

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有