MongoDB数据库查询性能提高40倍

MongoDB数据库查询性能提高40倍

大家在使用 MongoDB 的时候有没有碰到过性能问题呢?下面这篇文章主要给大家分享了MongoDB数据库查询性能提高40倍的经历,需要的朋友可以参考借鉴,下面来一起看看吧。

前言

数据库性能对软件整体性能有着至关重要的影响,本文给大家分享了一次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

实现难度当然是最低的,可是整个任务在第一步只有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}})# 下面就是取出结果,求平均数
...

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

可是,可是…… 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)

这次总该可以了。

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

返回值减负

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

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

总结

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/390007.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

通过Ajax方式上传文件(input file),使用FormData进行Ajax请求

<script type"text/jscript">$(function () {$("#btn_uploadimg").click(function () {var fileObj document.getElementById("FileUpload").files[0]; // js 获取文件对象if (typeof (fileObj) "undefined" || fileObj.size …

并发插入数据库会导致失败吗_会导致业务失败的数据分析方法

并发插入数据库会导致失败吗The true value of data depends on business insight.Data analysis is one of the most powerful resources an enterprise has. However, if the tools and processes used are not friendly and widely available to the business users who nee…

434. 字符串中的单词数

434. 字符串中的单词数 统计字符串中的单词个数&#xff0c;这里的单词指的是连续的不是空格的字符。 请注意&#xff0c;你可以假定字符串里不包括任何不可打印的字符。 示例: 输入: “Hello, my name is John” 输出: 5 解释: 这里的单词是指连续的不是空格的字符&#x…

zooland 新开源的RPC项目,希望大家在开发的微服务的时候多一种选择,让微服务开发简单,并且容易上手。...

zooland 我叫它动物园地&#xff0c;一个构思很长时间的一个项目。起初只是觉得各种通信框架都封装的很好了&#xff0c;但是就是差些兼容&#xff0c;防错&#xff0c;高可用。同时在使用上&#xff0c;不希望有多余的代码&#xff0c;像普通接口一样使用就可以了。 基于这些想…

187. 重复的DNA序列

187. 重复的DNA序列 所有 DNA 都由一系列缩写为 ‘A’&#xff0c;‘C’&#xff0c;‘G’ 和 ‘T’ 的核苷酸组成&#xff0c;例如&#xff1a;“ACGAATTCCG”。在研究 DNA 时&#xff0c;识别 DNA 中的重复序列有时会对研究非常有帮助。 编写一个函数来找出所有目标子串&am…

牛客网_Go语言相关练习_选择题(2)

注&#xff1a;题目来源均出自牛客网。 一、选择题 Map&#xff08;集合&#xff09;属于Go的内置类型&#xff0c;不需要引入其它库即可使用。 Go-Map_菜鸟教程 在函数声明中&#xff0c;返回的参数要么都有变量名&#xff0c;要么都没有。 C选项函数声明语法有错误&#xff0…

机器学习模型部署_9月版部署机器学习模型

机器学习模型部署每月版 (MONTHLY EDITION) Often, the last step of a Data Science task is deployment. Let’s say you’re working at a big corporation. You’re building a project for a customer of the corporation and you’ve created a model that performs well…

352. 将数据流变为多个不相交区间

352. 将数据流变为多个不相交区间 给你一个由非负整数 a1, a2, …, an 组成的数据流输入&#xff0c;请你将到目前为止看到的数字总结为不相交的区间列表。 实现 SummaryRanges 类&#xff1a; SummaryRanges() 使用一个空数据流初始化对象。void addNum(int val) 向数据流中…

Java常用的八种排序算法与代码实现

排序问题一直是程序员工作与面试的重点&#xff0c;今天特意整理研究下与大家共勉&#xff01;这里列出8种常见的经典排序&#xff0c;基本涵盖了所有的排序算法。 1.直接插入排序 我们经常会到这样一类排序问题&#xff1a;把新的数据插入到已经排好的数据列中。将第一个数和第…

熊猫ai智能机器人量化_机器学习中的熊猫是什么

熊猫ai智能机器人量化Machine learning is a complex discipline. The implementation of machine learning models is now far much easier than it used to be, this is as a result of Machine learning frameworks such as pandas. Wait!! isnt panda an animal? As I rec…

441. 排列硬币

441. 排列硬币 你总共有 n 枚硬币&#xff0c;并计划将它们按阶梯状排列。对于一个由 k 行组成的阶梯&#xff0c;其第 i 行必须正好有 i 枚硬币。阶梯的最后一行 可能 是不完整的。 给你一个数字 n &#xff0c;计算并返回可形成 完整阶梯行 的总行数。 示例 1&#xff1a;…

调用百度 Echarts 显示重庆市地图

因为 Echarts 官方不再提供地图数据的下载&#xff0c;在这里保存一份&#xff0c;供日后使用&#xff0c;重庆地图数据的 JSON 文件在 CSDN 上下载。 <!DOCTYPE html> <html style"height: 100%"><head><meta charset"utf-8"><…

JEESZ-SSO解决方案

2019独角兽企业重金招聘Python工程师标准>>> 第一节&#xff1a;单点登录简介 第一步&#xff1a;了解单点登录 SSO主要特点是: SSO应用之间使用Web协议(如HTTPS)&#xff0c;并且只有一个登录入口. SSO的体系中有下面三种角色: 1) User(多个) 2) Web应用(多个) 3) …

女朋友天天气我怎么办_关于我的天气很奇怪

女朋友天天气我怎么办带有扭曲的天气应用 (A Weather App with a Twist) Is My Weather Weird?™ is a weather app with a twist — it offers a simple answer to a common question we’ve all asked. To do this we look at how often weather like today’s used to happ…

Java中length,length(),size()的区别

&#xff08;一&#xff09;区别&#xff1a; ①length&#xff1a;用于算出数组的长度。 ②length&#xff08;&#xff09;&#xff1a;用于找出字符串的长度。 ③size&#xff08;&#xff09;&#xff1a;用于找出泛型集合的元素个数。转载于:https://www.cnblogs.com/not-…

5895. 获取单值网格的最小操作数

5895. 获取单值网格的最小操作数 给你一支股票价格的数据流。数据流中每一条记录包含一个 时间戳 和该时间点股票对应的 价格 。 不巧的是&#xff0c;由于股票市场内在的波动性&#xff0c;股票价格记录可能不是按时间顺序到来的。某些情况下&#xff0c;有的记录可能是错的…

为什么要用Redis

最近阅读了《Redis开发与运维》&#xff0c;非常不错。这里对书中的知识整理一下&#xff0c;方便自己回顾一下Redis的整个体系&#xff0c;来对相关知识点查漏补缺。我按照五点把书中的内容进行一下整理&#xff1a;为什么要选择Redis&#xff1a;介绍Redis的使用场景与使用Re…

第一次马拉松_成为数据科学家是一场马拉松而不是短跑

第一次马拉松Since Data Science became the “Sexiest Job of the 21st Century” the interest in the field has grown tremendously. With it so have the courses available to gain the necessary knowledge. As great as this is, the downside is a field marketed as …

273. 整数转换英文表示

273. 整数转换英文表示 将非负整数 num 转换为其对应的英文表示。 示例 1&#xff1a;输入&#xff1a;num 123 输出&#xff1a;"One Hundred Twenty Three" 示例 2&#xff1a;输入&#xff1a;num 12345 输出&#xff1a;"Twelve Thousand Three Hundred…

Java-运算符

算术运算符 加法 相加运算符两侧的值- 减法 左操作数减去右操作数* 乘法 相乘操作符两侧的值/ 除法 左操作数除以右操作数&#xff08;int类型的数相除时&#xff0c;会得到int类型的值&#xff0c;如果结果有小数&#xff0c;则小数部分会被舍弃&#xff09;% 模余运算&…