Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何从MongoDB中删除数据而不使其停止?_Mongodb - Fatal编程技术网

如何从MongoDB中删除数据而不使其停止?

如何从MongoDB中删除数据而不使其停止?,mongodb,Mongodb,每次我们使用collection.remove()从MongoDB中删除大量数据时,这会使数据库速度太慢,最终导致web服务器停机。我相信这是因为删除操作会在较长时间内锁定集合 我们有一个查询,它提供了我们想要删除的所有文档。但是,查询不包含日期/时间字段,因此我们不能使用TTL索引 是否有一种方法可以以nice的方式删除数据,不时释放锁?使用批量操作 批量操作在这里可能会有所帮助。无序的bulk.find(queryDoc).remove()基本上是针对大量操作而优化的db.collectio

每次我们使用
collection.remove()
从MongoDB中删除大量数据时,这会使数据库速度太慢,最终导致web服务器停机。我相信这是因为删除操作会在较长时间内锁定集合

我们有一个查询,它提供了我们想要删除的所有文档。但是,查询不包含日期/时间字段,因此我们不能使用TTL索引

是否有一种方法可以以
nice
的方式删除数据,不时释放锁?

使用批量操作 批量操作在这里可能会有所帮助。无序的
bulk.find(queryDoc).remove()
基本上是针对大量操作而优化的
db.collection.remove(queryDoc)
版本。它的用法非常简单:

var bulk=db.yourCollection.initializeUnderedBulkop()
bulk.find(yourQuery.remove)()
bulk.execute()
详情请参阅

这种方法背后的想法不是加快拆卸速度,而是减少负载。在我的测试中,负载减少了一半,所用的时间略少于
db.collection.remove(query)

创建索引 但是,删除操作不应使实例处于冻结状态。我在5年前的MacBook上测试了1200万个文档的删除,虽然它增加了一些负载,但距离冻结还很远,大约需要10分钟。但是,我用来查询的字段被编入了索引

这让我得出结论,您可能正在经历收集扫描。如果我是对的,那么会发生以下情况:您的查询包含未包含在索引中的字段或字段组合,或者无法为其构造索引交集。这迫使相关mongod从磁盘中查找、访问和读取数据库中每个文档的这些字段

因此,在执行删除操作之前,在后台创建一个包含查询中每个字段的索引可能会有所帮助,尽管这是违反直觉的

db.collection.createIndex(
  {firstFieldYouQueryBy:1,...,NthFieldYouQueryBy:1},
  {background:true}
)
尽管此操作将在后台完成,但shell将被阻止。 这可能需要一段时间。您可以通过打开第二个shell并使用以下命令来查看状态:

db.currentOp()
(你得搜索一下)

创建索引时(您可以使用
db.collection.getIndexes()
进行检查),您的删除操作应该更高效,因此速度更快。在质量移除完成后,当然可以删除索引,如果不需要的话

使用索引,可以防止收集扫描,从而大大加快删除速度

结合两种方法
显然,首先创建索引并在索引准备好后发出bulk命令是有意义的。

我的黑客解决方案:编写一个程序,查询所有要删除的文档的ID,将它们存储在数组/列表中。然后为它们中的每一个发出移除命令。但是这很慢这是过期的东西吗?文档是否有某种类型的日期字段?不幸的是,它们没有,否则我将使用TTL索引。这更像是一个移民的事情,正在进行吗?这听起来更像是数据模型的问题,而不是MongoDB的问题。我需要更多关于这方面的信息,比如示例文档、删除触发器等等。一般来说,没有,没有节流的方法。您可以使用批量操作,但听起来这是一种治疗症状的方法,而不是问题的原因。您可以将其称为我们的数据模型的问题,但我更愿意说,我们的需求发生了变化,我们希望采用我们的数据模型。为此,我们需要删除一些过时的文档(约1200万)。我们有一个查询,它为我们提供了1200万个文档,但该查询不涉及日期/时间字段。如何在这种情况下使用批量操作?我看了一下,但从文档中找不出如何使用它。嘿,马库斯,谢谢你的详细回答!你说得对,我们的查询没有使用索引。但是,在实时副本集上创建索引也是一个问题,它还会冻结我们的web应用程序服务器:-(.所以我们不能只创建一个索引,我们必须一个接一个地从副本集中删除每个节点,离线创建索引,然后将其重新连接到副本集中。删除一些文档似乎需要很多努力。此外,这还涉及到一个逐步删除和选择一个新的主节点,这意味着数据库实际上会关闭几秒钟。@BastianVoigt通过Skype与您联系,我认为有必要谈谈。很抱歉,我停止使用Skype,因为他们仍然没有64位linux版本。请发电子邮件给我,地址是bei bastian minus,voigt punkt de。有人能解释批量操作是如何降低服务器负载的吗?从文档中我不太清楚……嘿,我试过了这种方法,首先在我有时间戳的列上创建一个索引,然后运行批量删除查询。但它每秒删除50到80条记录。总收集大小为1TB