【问题标题】:Ways to handling huge transactions on any database?在任何数据库上处理大量事务的方法?
【发布时间】:2010-09-13 15:02:20
【问题描述】:

我有一个数据转换产品,它允许选择数据库中的表并将源数据库中的行数据转换到目标数据库。

这是在当前产品(基于 java 的工作台和引擎)中通过一次处理 1000 行并并行执行 10 个线程来处理的。这种方法适用于较小的数据集。但是,当我必须一次转换大量数据集(比如大约 X 百万条记录)时 - 这种方法仍然有效,但是

  • 运行我的产品的主机 CPU 负载过重。
  • 源数据库和目标数据库的事务过多,导致它们开始变慢。 (现在,这可能是因为数据库服务器可能运行在较慢的硬件上。)

我开始寻找解决方案,并通过在源/目标数据库服务器机器上请求硬件“加强”来快速解决这个问题。例如,这涉及购买新的多核 CPU 和一些额外的 RAM。事实证明,升级硬件不仅仅是唯一的问题:需要为数据库购买多个软件许可证 - 这要归功于多核处理器(每个核心许可证)。

所以,球现在在我的球场上,我必须想出办法来解决这个问题,通过对我的产品进行更改。而且,这里是我需要你帮助的地方。此时,我可以想到一种可能的方法来处理巨大的负载:

方法1

  1. 从源数据库读取数据,将其保存到临时介质(文件)中。
  2. 通过在分布式环境(更便宜的单核机器)中运行数据来转换持久文件中的数据,并在那里处理切换到文件持久性的“权衡移动”。 (使用 Apache Hadoop 之类的东西来处理分布式计算部分)
  3. 正在将数据写入目标数据库。

从架构的角度来看,这就是我目前所能想到的。 你以前处理过这种情况吗?如果是,您是如何处理的? 感谢您的建议和帮助。

【问题讨论】:

  • 什么是性能瓶颈?您提到了两个候选者:应用程序 CPU 负载和数据库负载。你能进一步缩小范围吗?
  • @oksayt 现在,我主要关心的是数据库负载。我没有这方面的基准,但我们的想法是通过考虑可能的瓶颈来构建更好的产品。

标签: java design-patterns architecture hardware


【解决方案1】:

在不增加数据库许可成本的情况下,您可以做以下几件事:

  • 假设您的工具在未运行数据库的计算机上运行,​​则您的工具将 CPU 置于重负载下,增加该计算机的 CPU 功率,或者如果您的工具允许它在多台计算机上运行。
  • 活动事务数量增加的原因之一是每个单独的事务都需要时间来完成。您可以通过优化磁盘或放入更快的磁盘来加快速度。

此外,如果您使用插入而不是批量插入,则存在巨大的改进潜力。普通插入的问题是它会将信息写入日志,以便可以回滚事务。

this 的情况下,我能够帮助某人将加载时间从 10 小时 减少到 6 分钟 :)

【讨论】:

  • +1 绝对是批量插入,如果不使用它可能是一个巨大的收获。
  • 感谢您提供指向案例研究的链接。我提出这个问题的目的是收集所有可能的解决方案来解决我的问题。我不希望您过于担心数据库事务作为瓶颈。如果您可以将分布式计算视为可能的解决方案之一,您会投票支持这样的解决方案吗?如果不是,解决这个问题的可能的非数据库方法是什么?
  • 您可以使用云名称值对数据存储,而不是使用本地关系数据库,但您的瓶颈将是您的互联网连接。然后,您还可以在运行导入时启动许多机器实例,并在导入完成时关闭它们。
  • 我猜,使用云名称值对数据存储,会对性能产生不利影响。是的,我想启动许多机器实例——但是如何管理所有这些实例?在这种情况下,您认为 Apache Hadoop 适合吗?
【解决方案2】:

分而治之!

如果源数据库不能同时处理这两个工作(ETL 和“常规”事务),那么不要让它受到影响:

  • 将源数据复制到“镜像”。
  • 在“镜像”上执行 ETL。

注意 - 当我说“镜像”时,我只是指允许快速有效地复制数据的副本(有点像“暂存”数据库) - 不是另一个大/慢/讨厌ETL 过程。这里的想法是优化流程以使源数据库受益。

然后,您可以优化目标数据库的ETL,以使目标数据库受益;因为您已经将源和目标分开,所以优化整个过程的读取/插入部分会更容易。

您也可以在目标端做类似的事情(使用另一个“镜像”/暂存数据库)。

这种方法与您建议的方法没有什么不同,但我假设在 相同类型的两个相同数据库之间直接复制数据将是最容易管理和效率最高。

之后,您可以开始应用其他人可以提出的其他一些建议。

最后一件事 - 你可以尝试使用 ETL 工具 - 如果你正在运行

【讨论】:

    【解决方案3】:

    您是否使用较小规模的事务对其进行了基准测试?否则我不会为此使用交易。从您的许可问题听起来您使用的是 oracle 或 sql server。它们都具有批量插入功能,这将比事务更匹配。

    【讨论】:

    • 不,我没有对它进行基准测试,或者更确切地说,它已经进行了基准测试,只是我现在没有统计数据。是的,我一直在针对 oracle 和 sql server 测试我的产品。我知道他们有导入/导出工具,但问题是,这些工具的效果如何?
    • 它们非常有效。几年前,我将它们与 sql 服务器一起使用,每晚将数百万条记录移动和处理到报告数据库中。这个过程大约需要 3 个小时,但必须对每条记录进行大量预处理。
    【解决方案4】:

    首先要考虑的是,您是否真的需要针对这么多数据进行交易。如果答案是否定的,那么您的数据库产品可能具有针对这种大型数据库插入的批量插入选项。

    编辑(进一步了解 cmets):我认为最划算(无论如何在 SQL Server 中)是在操作期间将目标数据库设置为简单恢复模式。事实上,如果您这样做了,您很可能不必进行任何其他代码更改。

    但是,这仅适用于目标数据库没有同时用于其他事情的情况。我会说这是一个基本要求。在 OLAP 事务处于活动状态时尝试将 2500 万条记录插入数据库是一个基本的数据库错误。如果这是绝对必要的,那么我认为解决方案是让进程变得非常缓慢(有明显的停顿),以便释放资源,使数据库能够继续运行。

    【讨论】:

    • 您的意思是,如果我要忽略事务,并找到一种方法来利用通常可供数据库使用的批量插入选项,它不会影响数据库的负载吗?那么,如果您要插入 2500 万条记录,使用导入实用程序,您的数据库对当前正在服务的所有请求的性能不会受到影响吗?如果有,您在这方面是否有任何参考资料?
    • 我不会说它们不受影响,但该操作已针对其正在执行的操作进行了优化。我看到您正在尝试同时使用 Oracle 和 SQLServer。您可以尝试对批量操作的 JDBC 支持,但我不确定驱动程序究竟做了什么。以下是一些在 SQL 中优化批量插入的文档:msdn.microsoft.com/en-us/library/ms190421%28v=SQL.105%29.aspx
    【解决方案5】:

    使用 oracle sql 加载器(导入/导出)。将数据导入中间表,一旦一切顺利,将主表重命名为备份后,将表重命名为主表。请记住,您应该仅在每次导入/上传后应用约束。你可以从java程序中调用sql loader。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-19
      • 1970-01-01
      • 2016-10-09
      相关资源
      最近更新 更多