Mongodb批量写入操作bulkWrite()

学习mongodb,体会mongodb的每一个使用细节,欢迎阅读威赞的文章。这是威赞发布的第76篇mongodb技术文章,欢迎浏览本专栏威赞发布的其他文章。如果您认为我的文章对您有帮助或者解决您的问题,欢迎在文章下面点个赞,或者关注威赞。谢谢。

概述

Mongodb提供了针对单一集合写操作批量执行的方法。在批量写操作当中,Mongodb也允许用户自由定义数据提交的方式。通过db.collection.bulkWrite()方法,用户能够对单一集合进行数据插入,更新和删除操作 。当然, 方法db.collection.insertMany()也是一种批量写入操作。

批量写操作的顺序

用户定义的批量操作,可以是顺序执行的,也可以不按照顺序执行。

在顺序执行操作当中,Mongodb按照用户定义的批量操作序列,一步一步的执行。当某一个写操作出现错误时,mongdb会退出当前执行序列,不再执行后续的操作。而在非顺序执行操作当中,Mongodb并行执行用户定义的每一个操作。在非顺序执行操作当中,任意一个操作出错不会影响其他操作的执行。

在分片集合当中,顺序执行操作会比非顺序执行操作慢。因为需要等待前面的步骤完成。

bulkWrite()操作,默认是顺序执行每一个操作。用户如果需要指定非顺序执行,需要在options中定义{ordered: false}

支持批量写入的方法

bulkWrite支持下面的几个方法, 每一个方法都按照文档的形式 定义在bulkWrite操作的过程数据中。

    • insertOne
    • updateOne
    • updateMany
    • replaceOne
    • deleteOne
    • deleteMany

应用

构建pizza文档并插入数据

db.pizzas.insertMany([{
    _id: 0, type: "pepperoni", size: "small", price: 4
},{
    _id: 1, type: "cheese", size: "medium", price: 7
},{
    _id: 2, type: "vegan", size: "large", price: 8
}])

构建批量数据更新语句,要求完成下面几个动作

  • 向集合中插入两条新数据

  • 更新cheese文档的价格

  • 删除pepperoni

  • 将vegan替换成新的文档tofu

    try {
    db.pizzas.bulkWrite( [
    { insertOne: { document: { _id: 3, type: "beef", size: "medium", price: 6 } } },
    { insertOne: { document: { _id: 4, type: "sausage", size: "large", price: 10 } } },
    { updateOne: {
    filter: { type: "cheese" },
    update: { $set: { price: 8 } }
    } },
    { deleteOne: { filter: { type: "pepperoni"} } },
    { replaceOne: {
    filter: { type: "vegan" },
    replacement: { type: "tofu", size: "small", price: 4 }
    } }
    ] )
    } catch( error ) {
    print( error )
    }

分片集中批量写入策略

在分片集中,大量的写入操作包括数据初始化,导入数据等可能会影响分片集的性能。因此,批量写入操作,可以考虑下面的策略

提前分片

mongodb中,空数据集只有一个初始数据块,放在单个分片当中。插入数据时,mongodb需要在接收数据,创建数据分块,将数据分块写入分片上消耗大量的时间。为了避免数据分块消耗的时间,用户可以提前将数据分好。

非顺序写入

为了在分片集中提高写入效率 ,用户可以将bulkWrite()方法的ordered参数设置为false。这样mongos可以尝试同时向多个分片写入数据。

避免在分片集中使用单调主键

如果片键在一次插入过程中单调递增,那么所有插入的数据都会进入集合的最后一个块,而这个块总是会出现在一个片上。因此,集群的插入容量永远不会超过该单个分片的插入容量。如果插入数据量大于单个分片所能处理的数据量,并且无法避免片键的单调递增,那么可以考虑对应用进行以下修改。反转片键的二进制位。这样可以保留信息,并避免将插入顺序与值的递增顺序关联起来。交换第一个和最后一个16位的单词来"打乱"插入操作。

相关推荐
十叶知秋1 分钟前
【jmeter】jmeter的线程组功能的详细介绍
数据库·jmeter·性能测试
瓜牛_gn2 小时前
mysql特性
数据库·mysql
奶糖趣多多3 小时前
Redis知识点
数据库·redis·缓存
CoderIsArt4 小时前
Redis的三种模式:主从模式,哨兵与集群模式
数据库·redis·缓存
师太,答应老衲吧6 小时前
SQL实战训练之,力扣:2020. 无流量的帐户数(递归)
数据库·sql·leetcode
Channing Lewis7 小时前
salesforce case可以新建一个roll up 字段,统计出这个case下的email数量吗
数据库·salesforce
毕业设计制作和分享8 小时前
ssm《数据库系统原理》课程平台的设计与实现+vue
前端·数据库·vue.js·oracle·mybatis
ketil278 小时前
Redis - String 字符串
数据库·redis·缓存
Hsu_kk9 小时前
MySQL 批量删除海量数据的几种方法
数据库·mysql
编程学无止境9 小时前
第02章 MySQL环境搭建
数据库·mysql