怎么对10亿数据量级的mongoDB作高效的全表扫描
转自:http://quentinxxz.iteye.com/blog/2149440
一、正常情况下,不应该有这种需求
首先,大家应该有个概念,标题中的这个问题,在大多情况下是一个伪命题,不应该被提出来。要知道,对于一般较大数据量的数据库,全表查询,这种操作一般情况下是不应该出现的,在做正常查询的时候,如果是范围查询,你至少应该要加上limit。
说一下,我的应用场景:用于全量建立搜索引擎的索引。这就是一种需要用到全表扫描的非一般情况。对于全表扫描的结果,我们没有排序要求。
二、情况说明
既然有如此大的数据量,那存储所占空间基本都是上T的了。所以肯定是使用了mongodb集群,而且配置了分片的分布式环境。
公司的服务器,性能比较好,应该是24核,96g内存的。所以读者们使用不同机器,测出来的用时,跟我这的结果可能不一定相符。
三、第一种方法,利用chunk信息作划分。
原理:我们知道,在分片环境下,mongodb使用chunk块来组织数据。同一个chunk块的数据肯定存在于同一个分片上。假设,我们以 “_id”作分片时所用的片键。Mongodb为了保证范围查找的效率,一定会将一定范围内的_id值的document方在同一个chunk中。而且通过mongodb自身提供的方法,我们可以很方便的获取,每一个chunk的中maxKey与minKey。[minKey,maxKey) 这个范围内的数据肯定在同一个chunk内,也并定在同一个分片中。
做法:1、先获取所有chunk信息,得到他们的maxKey与minKey。
2、多线程执行,将这些chunk信息,分发给这些执行线程。
3、各线程,根据当前的chunk与 maxKey与minKey信息,做范围查找。
4、最后将结果汇总。
这样做的好处在于:
1、每次对一个chunk做的范围查找,肯定是只在一个分片(意味着同一块硬盘)中进行的,不会分散到多个分片。这样很高效。
2、可以方便的利用多线程,提高效率。
这种方法我没试过,公司的前辈尝试过,据说,最终用时3小时以内。是最为理想的效果。
四、改用散列片键后的全表扫描方法
用上面的方法,有一个前题,就是分片策略采用的是mongodb默认的升序片键的方法。这样才保证,升序的_id,会按排序范围分布在chunk块中。这样这策略,存在一个明显的问题,就是会造成所以新增的doucument的写入肯定都会命中到具有当前最大_id的chunk上。造成写入的分发的不平衡。
前文中,说过,全表扫描,应该是一个正常情况下不被允许的情况。所以数据库策略的制定也不应该以考虑全表扫描的效率为优先,当前情况下,就应以写入效为优先考虑。公司正在使用的片键策略,是片键策略散列片键(hashed shard key),这样的话,写入请况会被很好地分发到多个分片上,但是不利用进行范围查找。上面用的全表扫描方法就没法再用了。
做法:1、获得全局的最大id maxID与全局的最小id minID。
2、设置一个stepSize ,比如5000。将[minID,maxID]按5000为一个chunk(我们定义的一个逻辑chunk)作切分,那么第一个块范围[minID,minID+5000),
3、各线程,根据分配到的chunk块的maxID与minID信息,做范围查找。
4、最后将结果汇总。
这样做法的问题:
1、对一个chunk进行查询,会命中多个分片进行查询,查询效率大幅降低。
2、 如果_id分布稀疏,查询变得更快。因为以5000为stepSize, 其中可能有不少_id是不存在的。测试同学帮我搭线下测试数据时,2000w条数据,由于计算错误,_id的范围分布剧然从10亿起,到130亿止。导致的线程几乎一起在空跑chunk。所以_id分布稀疏的情况下,这种查询方式完全不适用。
3、 _id分布不均。可能某个chunk中几乎5000个满载,有些chunk只有很少几个_id有效。那么就会导致计算资源分布不均。
最后的结果不理想,我一开始,由于涉及一些联表join操作,用时16多个小时。后来各种调整,加线程,去掉一些操作,差不多仍需10小时。
五、改用散列片键后的较高效全表扫描方法
上面的那种方法,当然是不理想的。光查数据就需要16个小时,加上后续处理,肯定更久,这样我们的搜索引擎索引建立,就不可能当前完成了。但一直苦于没有更好的方法。
最终这个问题,还是被我的头解决了。 先说一下,最终效果吧。20w条/秒,约3小时完成。
其实,最终的方法很简单,但必须放弃多线程(多cursor),至多一个分片一个线程。
做法:使用单线程扫描,不加适合可能影响排序的条件。
这样做的目的是使用mongodb中的自然排序。扫描时,必然是依次命中某一个分片读取,不会带来磁盘震荡问题。
怎么对10亿数据量级的mongoDB作高效的全表扫描的更多相关文章
- MongoDB 定位 oplog 必须全表扫描吗?
MongoDB oplog (类似于 MySQL binlog) 记录数据库的所有修改操作,除了用于主备同步:oplog 还能玩出很多花样,比如 全量备份 + 增量备份所有的 oplog,就能实现 M ...
- SQL 数据优化索引建suo避免全表扫描
首先什么是全表扫描和索引扫描?全表扫描所有数据过一遍才能显示数据结果,索引扫描就是索引,只需要扫描一部分数据就可以得到结果.如果数据没建立索引. 无索引的情况下搜索数据的速度和占用内存就会比用索引的检 ...
- [SQL]会引起全表扫描的10种SQL语句
1.模糊查询效率很低: 原因:like本身效率就比较低,应该尽量避免查询条件使用like:对于like ‘%...%’(全模糊)这样的条件,是无法使用索引的,全表扫描自然效率很低:另外,由于匹配算法的 ...
- 这么设计,Redis 10亿数据量只需要100MB内存
本文主要和大家分享一下redis的高级特性:bit位操作. 本文redis试验代码基于如下环境: 操作系统:Mac OS 64位 版本:Redis 5.0.7 64 bit 运行模式:standalo ...
- Oracle-查询最近更新的前10条数据
在实际用途中,常常会要求取最近的几条纪录,这就需要先对纪录进行排序后再取rownum <= 一般常见的 SELECT * FROM (SELECT a.* FROM torderdetail a ...
- 转 DataTorrent 1.0每秒处理超过10亿个实时事件
DataTorrent是一个实时的流式处理和分析平台,它每秒可以处理超过10亿个实时事件. 与Twitter平均每秒大约6000条微博相比,最近发布的DataTorrent 1.0似乎已经超出了需求, ...
- 【转载】TalkingData首席金融行业专家鲍忠铁:18亿数据解读移动互联网
http://www.36dsj.com/archives/33417 鲍忠铁:大家下午好! 今天我会讲三个议题,一是用18亿数据解读现在移动互联网的生态圈.二是看看数据有什么样的应用.三是大数据的隐 ...
- python 读取SQLServer数据插入到MongoDB数据库中
# -*- coding: utf-8 -*-import pyodbcimport osimport csvimport pymongofrom pymongo import ASCENDING, ...
- 使用HAProxy、PHP、Redis和MySQL支撑每周10亿请求
在公司的发展中,保证服务器的可扩展性对于扩大企业的市场需要具有重要作用,因此,这对架构师提出了一定的要求.Octivi联合创始人兼软件架构师Antoni Orfin将向你介绍一个非常简单的架构,使用H ...
随机推荐
- esp8266 + dht11 + 两路继电器 实现pc远程控制开关机温度监控.并配置zabbix监控
事因:翻了翻自己之前的硬件小箱子,几年前买的一些小东西,想用用起来. 正好我有些数据放在机器上,有时候需要机器启动,我使用完成后在断开. 其实网络唤醒也能做到,但是机器一直给电也不好,在说家里有小孩A ...
- 连接linux的几款工具 简介
1.Putty --支持ppk,pub格式密码连接 --支持centos --支持windows操作系统安装,网上去下载直接可以使用,免费的 安装文件在我的百度网盘:putty 安装后如下: load ...
- BufferedReader和BufferedWriter简介
BufferedReader和BufferedWriter简介 为了提高字符流读写的效率,引入了缓冲机制,进行字符批量的读写,提高了单个字符读写的效率.BufferedReader用于加快读取字符的速 ...
- SpringBoot 配置Druid:不显示SQL监控 —(*) property for user to setup
题外话: SpringBoot整合Druid 请查看https://www.cnblogs.com/JealousGirl/p/druid.html Druid登录后数据源页面.SQL监控等不显示数据 ...
- 【转】python requests库添加自定义cookie的方法
requests库是个很方便的爬虫,相关文档已经很详细了.不过我今天在爬网页时,有一个网站是在脚本中添加cookie的,但我向requests.cookies里添加cookie费了不少周折.尝试了多个 ...
- Spark(五十二):Spark Scheduler模块之DAGScheduler流程
导入 从一个Job运行过程中来看DAGScheduler是运行在Driver端的,其工作流程如下图: 图中涉及到的词汇概念: 1. RDD——Resillient Distributed Datase ...
- ubuntu下搭建nfs服务
1. 安装nfs服务端 $ sudo apt install nfs-kernel-server -y 2. 创建目录 $ sudo mkdir -p /mnt/sharefolder 3. 使任何客 ...
- PHP如何防止注入及开发安全
1.PHP注入的基本原理 程序员的水平及经验也参差不齐,相当大一部分程序员在编写代码的时候,没有对 用户输入数据的合法性进行判断,使应用程序存在安全隐患.用户可以提交一段数据 库查询代码,根据程序返回 ...
- pythonUDP发送结构体,对齐到C++结构体
给出程序先: import random import socket import struct import threading import pickle import json from str ...
- 123457123456#1#----com.ppGame.BaoBaoiMiYu35--前拼后广--miyu_pp
com.ppGame.BaoBaoiMiYu35--前拼后广--miyu_pp