假设我有一个庞大的MongoDB收藏集。每天晚上,我都希望对其进行查询,并按当前未建立索引的字段进行过滤。我不在乎查询要花多长时间(我将对其进行监控,如果开始花费的时间超过几个小时,我会重新考虑)。因此,我不想只为该查询建立索引,因为每个索引都会带来一些操作开销。
但是,我要做的关心的是,此完整扫描不会对该MongoDB实例上的任何其他命令产生不利影响。它不能锁定任何东西,不要使我的磁盘I / O停顿下来,等等。
如果这是一个单独的Linux进程,则可以在nice
和/或ionice
下运行它。
我/我是否需要在MongoDB上采取任何类似的预防措施?还是默认情况下完整扫描通常是安全的?如果“取决于”,那又是什么?
假设运行在典型服务器硬件上的典型Linux系统。
答案 0 :(得分:1)
如果您不使用分片群集,但使用的是副本集,并且可以使用过时的数据,则可以read from a secondary:
db.collection.find({ ... }).readPref("secondary");
在运行分析/报告查询时,这是一个好主意,因为它们通常会占用大量资源并且需要长时间运行,因此,如果这些查询/报告在主数据库上运行,则会影响来自应用程序的读写。
MongoDB平衡器是一个后台进程,用于监视每个分片上的块数。当给定分片上的块数达到特定的迁移阈值时,平衡器将尝试自动在分片之间迁移块,并使每个分片上的块数均相等。
从分片群集上的辅助数据库读取数据的问题是,当此进程正在运行或已中止时,您可能会得到重复的,孤立的,陈旧的或丢失的数据。
请参见https://jira.mongodb.org/browse/SERVER-5931。
但是,看来该问题已在3.6
中得到修复,但是无论在release notes还是changelog中都找不到关于此问题的提及。
如果您使用的是MongoDB 3.6
或更高版本,则可以尝试一下此解决方案,否则,您可以等待其他人对此有所了解。
您也可以考虑创建索引以加快单个辅助数据库上的查询的速度,
Setting priority = 0
,这样该节点就不能成为主要节点,否则,由于为此更新分析/报告索引的额外开销,应用程序的性能(尤其是写入性能)将急剧下降节点。
Using a hidden node,即使副本集的读取首选项设置为secondary
,也可以防止与副本集的连接将读取路由到该特定节点。
但是,如果您使用3个成员副本集,则具有一个隐藏节点意味着如果其他2个节点掉线,则第三个(隐藏)节点将不会处理client reads。您可能会补偿5个成员(隐藏1个)而不是3个成员。
Using a delayed node,其中should also have priority = 0
and be hidden。
Using replica set tag sets和read preference将分析/报告查询路由到特定节点,这些节点具有priority = 0
但不会被隐藏,因此它们可以从客户端读取数据。这还提供了其他方法所没有的additional flexibility。
答案 1 :(得分:1)
这取决于以下各项的组合:
WiredTiger需要先将文档加载到其缓存中,然后才能操纵它们或将它们作为查询答复返回。这意味着进行集合扫描将用共同扫描的集合替换缓存的内容。
如果收集的集合没有形成您的典型工作集,那么当您需要集群进行工作时,它将需要再次从磁盘重新加载工作集。重新填充缓存时,这可能会显示为慢查询,具体取决于磁盘可以满足请求的速度。
换句话说,集合扫描相对于典型工作集将构成工作模式的变化,因此,在工作量变化期间应该会出现一些延迟。
除此之外,WiredTiger是一个乐观的并发存储引擎,除了全局元数据更改(放置收集,放置数据库等)期间,它并没有真正锁定其他任何内容。如果发生冲突,它将透明地重试写入,并且不会因MVCC阻止读取器。您所描述的工作应该是磁盘性能的瓶颈,而不是任何东西。
注意:上述WiredTiger中的乐观并发仅适用于副本集的主节点。在应用oplog期间,二级数据库会阻止读取,因为在应用oplog期间可能会出现数据库不一致的情况。