本文链接: 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中的自然排序。扫描时,必然是依次命中某一个分片读取,不会带来磁盘震荡问题。
相关推荐
Mongodb亿级数据量的性能测试 测试项目 分析测试结果
mongodb测试数据,学习增删改查等,或是用于性能测试
Mongodb亿级数据量的性能测试。各种测试方案结果。
使用java向mongodb中插入数据 一、Linux安装mongodb 二、MongoDB客户端工具(MongoVUE)访问mongodb 三、通过Java操作MongoDB
SqlServer数据导入MongoDBSqlServer数据导入MongoDBSqlServer数据导入MongoDB
MongoDB multiple Data center,官方推荐的指导文档。
SpringBoot+MongoDB+Echarts图表数据可视化 SpringBoot+MongoDB+Echarts图表数据可视化
MongoDB大数据处理权威指南 MongoDB大数据处理权威指南 MongoDB大数据处理权威指南
将mongodb矢量数据在geoserver中发布;将mongodb矢量数据在geoserver中发布
1、连接数据库 1、使用数据库、创建数据库 2、查看数据库 3、显示当前的数据集合(mysql 中叫表) 4、删除集合,删除指定的集合 5、删除数据库,删除当前
mongoDB实现企业bom表多试图转化技术
Spark-Mongodb是一个库允许用户利用Spark SQL读写数据至MongoDB集合
MongoDB的元数据与数据类型.pdf 学习资料 复习资料 教学资源
Mongodb 10亿级数据实时查询的小示例,还是很快的
MongoDB权威指南(第2版) 文字版 非扫描, 假一赔十。
主要为大家分享下1亿条记录的MongoDB数据库随机查询性能测试结果,需要的朋友可以参考下
教程名称:从浅入深学习 MongoDB视频教程全集 课程目录:【】MongoDB视频教程-00_MongoDB代码【】MongoDB视频教程01_第一讲_上【】MongoDB视频教程02_第一讲_下【】MongoDB视频教程03_第二讲_上【】MongoDB视频教程...
报告说明了在Windows平台下,mysql和mongodb插入数据的性能时间对比。
MongoDB热温数据的最佳实践.pdf