本文链接: 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的理解,提升数据库管理技能。
Python有PyMongo库用于与MongoDB交互,包括连接数据库、创建集合(类似表)、插入数据、查询数据等操作。 6. **数据存储与结构设计**:在MongoDB中,我们需要设计合适的文档结构(JSON格式)来存储房价信息,如包含...
MongoDB通过数据中心感知的复制、缩放和操作自动化,帮助组织在多个数据中心之间高效地部署和管理全球应用。此外,业务连续性和用户体验是驱动数据库跨地域部署的两个主要原因。 业务连续性指的是,无论数据库是...
5. **查询优化**:编写高效的查询语句,避免使用可能导致全表扫描的操作。 测试结果表明,尽管MongoDB在内存中的查询性能非常出色,但必须注意控制并发度以防止CPU过载。在实际生产环境中,应结合监控工具持续跟踪...
Geoserver发布MongoDB矢量数据地图服务 Geoserver是一款功能强大且开源的地理信息系统(GIS)服务器,能够实现空间数据的存储、处理和发布。MongoDB是一款NoSQL数据库,能够存储大量的矢量数据。本文将介绍如何使用...
综上所述,"SpringBoot+MongoDB+Echarts图表数据可视化"项目利用SpringBoot作为后端处理逻辑,MongoDB作为数据存储,Echarts作为前端数据展示工具,共同实现了高效、直观的数据可视化解决方案。这个组合在现代Web...
但是,插入数据必须发生在集合(类似于关系数据库中的表)中,如 `db.user.insert({“name”:”xiaoming”})`。 创建数据库后,你可以使用 `show dbs` 查看所有数据库,而 `show collections` 用于显示当前数据库中...
Spark-MongoDB库将这两者完美结合,实现了在Spark上对MongoDB数据集的高效读写。 首先,让我们详细了解一下如何在Spark中使用Spark-MongoDB库进行数据读取。要连接到MongoDB,你需要配置MongoDB的URI(包括数据库名...
MongoDB的数据存储结构以“数据库-集合-文档”的层次形式组织,类似于传统数据库中的“表-行”。 在安装MongoDB之前,我们需要关注版本的选择。MongoDB的版本命名规范为x.y.z,其中y为奇数的版本号表示开发版,而y...
1. 数据准备:确定要迁移的数据表和字段,分析数据类型是否与MongoDB兼容。由于MongoDB支持JSON格式,因此,复杂的数据结构,如嵌套对象和数组,可以直接映射到MongoDB的文档结构。 2. 数据转换:根据MongoDB的数据...
MongoDB与Oracle数据库的数据同步是现代企业数据管理中常见的需求,尤其在大数据处理和分布式系统中。MongoDB是一个流行的文档型数据库,而Oracle则是一款成熟的SQL关系型数据库。本示例将探讨如何通过Java实现...
MongoDB热温数据最佳实践是针对数据库管理策略的一种优化方法,旨在提高系统性能并降低成本。在数据库中,数据被分为热数据、温数据和冷数据三类。热数据是指经常被访问的数据,温数据则是访问频率较低的数据,而冷...
总之,通过MongoDB和Java的结合,我们可以高效地实现企业BOM表的多视图转换。这个过程涉及数据库设计、数据读写、转换逻辑实现等多个方面,需要综合运用数据库管理和编程技术。理解BOM的业务逻辑,合理利用MongoDB的...
而对于小规模数据或单条记录的批量插入,MongoDB则更加高效。 - 在资源消耗方面,MongoDB相比于MySQL更加轻量级,特别是在处理小批次数据时,其对CPU和内存的影响较小。 - 选择哪种数据库应根据具体的应用场景来决定...
本文以一个实际案例——将10亿级的Elasticsearch (ES) 数据迁移到MongoDB,探讨了这一迁移过程中的成本和性能变化,以及两种数据库的适用场景。 首先,Elasticsearch通常被用于大数据量的全文搜索、模糊匹配和复杂...
例如,开发者可能通过Node.js或者JavaScript的MongoDB驱动程序(如mongoose或mongodb-native)来连接数据库,执行查询语句获取10亿级的数据。然后,他们可能会使用D3.js的API来创建一个数据绑定的SVG元素,如动态的...