更新集合中的大量记录

2023-11-25

我有一个名为TimeSheet现在有几千条记录。这最终将在一年内增加到 3 亿条记录。在这个集合中,我嵌入了另一个名为的集合中的一些字段Department大多数情况下不会得到任何更新,只有很少的记录会被更新。我所说的很少是指一年中只有一两次,也不是所有记录,只是集合中不到 1% 的记录。

大多数情况下,部门创建后就不会进行任何更新,即使有更新,也会在初始时完成(当TimeSheet中相关记录不多时)

现在,如果有人在一年后更新一个部门,在最坏的情况下,有机会收集TimeSheet总共将有约3亿条记录,以及更新的部门的约500万条匹配记录。更新查询条件将在索引字段上。

由于此更新非常耗时并且会创建锁,我想知道是否有更好的方法来做到这一点?我想的一个选择是通过添加额外的条件来批量运行更新查询UpdatedDateTime> somedate && UpdatedDateTime < somedate.

其他详情:

单个文档大小可能约为 3 或 4 KB 我们有一个包含三个副本的副本集。

还有其他更好的方法吗?对于这样的设计你怎么看?如果我给出的数字不像下面这样,你觉得怎么样?

1)更新查询总记录1亿条,匹配记录10万条

2)更新查询总记录1000万条,匹配记录10000条

3)更新查询总记录100万条,匹配1000条记录

注:集合名称department and timesheet,它们的目的是虚构的,不是真正的收藏,但我给出的统计数据是真实的。


让我根据我的全球知识和经验给你一些提示:

使用较短的字段名称

MongoDB 为每个文档存储相同的密钥。这种重复会导致磁盘空间增加。对于像您这样的非常大的数据库来说,这可能会产生一些性能问题。

Pros:

  • 文档大小较小,因此磁盘空间较小
  • RAM 中可容纳更多文档(更多缓存)
  • 在某些情况下 do 索引的大小会更小

Cons:

  • 不太可读的名称

优化索引大小

索引大小越小,它就越适合 RAM,并且索引丢失的情况也就越少。例如,考虑 git 提交的 SHA1 哈希值。 git 提交很多时候由前 5-6 个字符表示。然后只需存储 5-6 个字符而不是所有哈希值。

了解填充因子

对于文档中发生的更新导致昂贵的文档移动。此文档移动导致删除旧文档并将其更新到新的空位置并更新索引,这是昂贵的。

我们需要确保文档在发生更新时不会移动。对于每个集合,都涉及一个填充因子,它告诉在文档插入期间,除了实际文档大小之外要分配多少额外空间。

您可以使用以下命令查看集合填充因子:

db.collection.stats().paddingFactor

手动添加填充

就您而言,您很肯定会从一个会增长的小文档开始。稍后更新文档将导致多个文档移动。因此最好为文档添加填充。不幸的是,没有简单的方法来添加填充。我们可以通过在插入时向某个键添加一些随机字节,然后在下一个更新查询中删除该键来实现。

最后,如果您确定某些键将来会出现在文档中,请为这些键预先分配一些默认值,以便进一步的更新不会导致文档大小的增长,从而导致文档移动。

您可以获得有关导致文档移动的查询的详细信息:

db.system.profile.find({ moved: { $exists : true } })

大量集合 VS 少量集合中的大量文档

架构取决于应用程序的需求。如果有一个巨大的集合,其中我们只查询最近N天的数据,那么我们可以选择单独的集合,并且可以安全地归档旧数据。这将确保 RAM 中的缓存正确完成。

创建的每个集合都会产生比创建集合的成本更高的成本。每个集合的最小大小为几 KB + 一个索引 (8 KB)。每个集合都有一个关联的命名空间,默认情况下我们有一些 24K 命名空间。例如,每个用户都有一个集合是一个糟糕的选择,因为它不可扩展。过了某个时刻,Mongo 将不允许我们创建新的索引集合。

一般来说,拥有许多集合不会造成明显的性能损失。例如,如果我们知道我们总是基于月份进行查询,那么我们可以选择每月一次收集。

数据非规范化

始终建议将查询或查询序列的所有相关数据保留在同一磁盘位置。您需要在不同的文档中复制信息。例如,在博客文章中,您需要将帖子的评论存储在帖子文档中。

Pros:

  • 随着索引条目数量的减少,索引大小将非常小
  • 查询将非常快,其中包括获取所有必要的详细信息
  • 文档大小将与页面大小相当,这意味着当我们将此数据放入 RAM 中时,大多数时候我们不会将其他数据带入页面
  • 文档移动将确保我们释放一个页面,而不是页面中可能不会在进一步插入中使用的一小部分

上限集合

上限集合的行为类似于循环缓冲区。它们是特殊类型的固定大小集合。这些集合可以接收非常高速的写入和顺序读取。由于大小固定,一旦分配的空间被填满,新文档就会通过删除旧文档来写入。但是,仅当更新的文档适合原始文档大小时才允许文档更新(使用填充以获得更大的灵活性)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

更新集合中的大量记录 的相关文章

随机推荐

  • 编码技巧 - 交集类型和 java 枚举 [关闭]

    Closed 这个问题需要细节或清晰度 目前不接受答案 交集类型允许您 有点 执行具有继承层次结构的枚举 您不能继承实现 但可以将其委托给辅助类 enum Foo1 implements Bar enum Foo2 implements B
  • F#:异步、任务和 PLINQ,天哪!

    当F 问世时 我将在异步 并行编程领域获得财富 一个回答这个问题很好地描述了任务 并行 LINQ 和响应式框架之间的差异 但我想知道异步工作流程到底是如何适应这种情况的 如果我错了 请纠正我 但据我了解 异步工作流程将是处理 IO 绑定操作
  • 如何在GridView中创建删除按钮?

    我在我的另一个专栏GridView称为删除 单击删除时 应删除该行 换句话说 我需要获取当前行的用户名才能将其删除 我应该使用哪个事件 行删除 行删除等 如何从当前行获取用户名 这是一篇关于DataGrid的典型用法 Enjoy
  • Horizo​​ntalScrollView 在 RTL 模式下不会向左滚动

    我有 Horizo ntalScrollViewandroid supportsRtl true 在我的应用程序中 但它不是向左滚动 而是向右滚动 我该如何解决这个问题
  • 如何在 Python 中运行单元测试时临时隐藏 stdout 或 stderr

    我有一个错误的第三方 python 模块 在导入时输出到 stdout 或 stderr 这破坏了我的单元测试的输出 如何临时重定向stdout以隐藏其输出 限制为 Python 2 5 语法 Update 我忘记说了sys stdout
  • 转换 tex 源,以便所有宏都被它们的定义替换

    是否可以看到 TeX 预处理器 的输出 i e 实际输出完成之前的中间步骤 但所有用户定义的宏都被替换 只留下 TeX 原语的子集 或者说没有这样的中间步骤 Write edef xxx Any text with any commands
  • Rails 3 路线:DRY 成员

    我需要将以下成员方法添加到许多资源中 有没有办法将其干燥 member do get votes post up vote post down vote end 在我的routes rb中 resources news do resourc
  • 找不到类 java.io.ByteArrayInputStream 的序列化器

    从 openfire Rest api 获取用户实体时 我收到以下错误消息 我用 openfire Restapi 端点包装我的 Api 端点 error 内部服务器错误 异常 org springframework http conver
  • 使用opencv进行外在矩阵计算

    我正在使用 opencv 来校准我的网络摄像头 因此 我所做的是将网络摄像头固定在装备上 使其保持静态 并且我使用了棋盘校准图案并将其移动到摄像头前面 并使用检测到的点来计算校准 所以 我们可以在许多 opencv 示例中找到这一点 htt
  • 任务 <> 不包含“GetAwaiter”的定义

    Client iGame Channel new ChannelFactory
  • 如何将 java.util.Date 转换为 java.sql.Date?

    我正在尝试使用java util Date作为输入 然后用它创建一个查询 所以我需要一个java sql Date 我惊讶地发现它无法隐式或显式地进行转换 但我什至不知道如何做到这一点 因为 Java API 对我来说仍然相当新 没关系 p
  • 使用单独的文件来维护实体框架的连接字符串

    我的连接字符串当前位于我的 web config 文件中 是否可以将其放在单独的文件中并将实体框架指向它 我在这里找到了答案将 ConnectionStrings 和 mailSettings 从 web config 中分离出来 可能的
  • 如何获取 $_POST 数组的子集,其中键以前缀开头

    就说我的 POST变量看起来像
  • 如何使用凭据测试写入文件共享路径?

    我有一个数组Credential对象 我想测试这些凭据是否有权将文件写入文件共享 我想做类似的事情 myPath path to my share test txt foreach cred in credentialList Testin
  • 已弃用:窗口:orientationchange 事件

    The 方向改变事件已被弃用 window addEventListener orientationchange function event console log event target screen orientation angl
  • Android 模拟器在 Ubuntu 18.04 上因 SIGSEGV 崩溃

    Android Studio版本 Android Studio 3 1 2 内部版本 AI 173 4720617 建于 2018 年 4 月 14 日 它是从 Ubuntu 的 snap 商店安装的 我使用安装了kvm1 在 Ubuntu
  • 带有 UTF-8 字节顺序标记的 Excel 文件会导致错误

    我只是想知道是否有任何可能的方法来解决这个问题 我在工作中收到包含光纤接头拼接信息的 Excel 文件 当我尝试导入时 我收到一个输出错误 指出第一个表与预期看到的内容不匹配 当我打开它时 我可以看到 UTF 8 的 BOM 为 就在这个词
  • 如何使用QEMU和KGDB调试Linux内核?

    我已经能够使用以下方式启动基于 powerpc 的系统 具体来说是 MPC8544DS 来调用 qemu v1 7 0 qemu system ppc M mpc8544ds m 512 kernel zImage s nographic
  • .htaccess:检查查询字符串是否具有特定值,否则重定向它

    我正在尝试学习一些 htaccess 并且对它的功能感到非常焦虑 我在网上看到了一个片段 但无法让它工作 它基本上是这样的如果查询字符串没有特定值 则将其重定向到index php相反或其他一些页面 我怎么做 这是寻找价值apples ww
  • 更新集合中的大量记录

    我有一个名为TimeSheet现在有几千条记录 这最终将在一年内增加到 3 亿条记录 在这个集合中 我嵌入了另一个名为的集合中的一些字段Department大多数情况下不会得到任何更新 只有很少的记录会被更新 我所说的很少是指一年中只有一两