【问题标题】:Architecting a high performing "inserting solution"构建高性能的“插入解决方案”
【发布时间】:2015-07-05 14:58:09
【问题描述】:

我的任务是整合一个解决方案,该解决方案可以处理对数据库的高级插入。会有很多来自网页的 AJAX 类型调用。它不仅仅是一个网站/页面,而是几个不同的网站/页面。

它将处理跟踪人们在网站上的行为,由各种 javascript 事件等触发。

解决方案能够处理繁重的数据库插入负载非常重要。 插入后,我不介意将数据迁移到替代/补充数据存储。

我们最初考虑在 MongoDB 中使用 MEAN 堆栈并将一些数据迁移到 MySql 以用于报告目的。我也想知道在插入数据库或缓存之前使用某种队列,如memcached

我没有设法在其他地方找到太多帮助。我确实看到了this post,但它现在已经快 5 年了,感觉有点过时了,不太会问同样的问题。

非常感谢您的想法和想法。谢谢。

【问题讨论】:

    标签: database database-design architecture mean-stack


    【解决方案1】:

    为什么你需要一个堆栈?您是否正在寻找一个网络应用程序来进行插入?或者你已经有申请了?

    值得怀疑的是,任何缓存层在插入方面都会超过您的 NoSQL 数据库,但您可能应该确认您甚至需要 NoSQL 数据库。 MySQL 具有相当可靠的原始插入性能,只要您的负载可以在单个盒子上处理。大多数 NoSQL 解决方案可以更好地横向扩展。 This 可能值得一读。但实际上,如果您已经在内部拥有 MySQL,并且您将报告与插入实例分开,那么您可能会使用 MySQL。

    【讨论】:

    • 谢谢@Rob,您能否详细说明“只要您的负载可以在一个盒子上处理”?你的意思是只要你有足够的硬件?此外,这是一个“从头开始”的项目,我们不受任何特定数据库的约束。
    • 很多 NoSQL 解决方案横向扩展的特别好,MySQL 麻烦很多,主要是因为整个多主复制的复杂性。 scale-out-blog.blogspot.com/2012/04/… 给出了这个问题空间的一些很好的概述。但是,如果您不需要处理这种复杂性(因为单台机器可以处理吞吐量)。需要明确的是,一台(体面的)机器很可能能够处理大量的原始插入(每秒 25k 是很正常的)。
    • 如果你需要更多,那么像 Cassandra 这样的东西可能更合适。它的实例数量相当平坦。
    【解决方案2】:

    一些初步理论

    要了解如何针对繁重的插入工作量进行优化,我建议了解在数据库中插入数据所涉及的主要开销。一旦了解了各种开销,所有优化之王自然会出现。好处是你们都会对解决方案更有信心,对数据库有更多的了解,并且可以将这些优化应用到多个引擎(MySQL、PostgreSQl、Oracle 等)。

    我首先列出了插入开销的非详尽列表,然后展示了避免此类开销的简单解决方案。

    1. SQL 查询开销: 为了与数据库通信,您首先需要创建与服务器的网络连接、传递凭据、验证凭据、序列化数据并通过网络发送,等等。 并且一旦查询被接受,就需要对其进行解析,对其语法进行验证,必须对数据类型进行解析和验证,查询所搜索到的对象(表、索引等)以及访问权限进行检查等等。这些步骤(我确信我在这里忘记了很多事情)在插入单个值时代表了显着的开销。开销如此之大,以至于某些数据库,例如Oracle,有一个 SQL 缓存来避免这些开销。

    解决方案:重用数据库连接,使用准备好的语句,并在每个 SQL 查询中插入许多值(1000 到 100000)。

    2.确保强 ACID 保证: 数据库的 ACID 属性是以提前记录对数据库的所有逻辑和物理修改为代价的,并且需要复杂的同步技术(细粒度锁定和/或快照隔离)。处理 ACID 保证所需的实际时间可能比在数据库页面中实际复制 200B 行所需的时间高几个数量级。

    解决方案: 在表中导入数据时禁用撤消/重做日志记录。或者,您也可以 (1) 降低隔离级别以权衡较弱的 ACID 保证以降低开销或 (2) 使用异步提交(允许数据库引擎在重做日志正确硬化到磁盘之前完成插入的功能) .

    3.更新物理设计/数据库约束: 在表中插入值通常需要更新多个索引、物化视图和/或执行各种触发器。这些开销很容易再次支配插入时间。

    解决方案:您可以考虑在插入/导入期间删除所有辅助数据结构(索引、物化视图、触发器)。完成大部分插入后,您可以重新创建它们。例如,从头开始创建索引比通过单独插入填充索引要快得多。

    在实践中

    现在让我们看看我们如何将这些概念应用到您的特定设计中。我在您的案例中看到的主要问题是插入请求是由许多分布式客户端发送的,因此对插入进行批量处理的机会很小。

    您可以考虑在您最终拥有的任何数据库引擎前面添加一个缓存层。我认为 memcached 不适合实现这样的缓存层——memcached 通常用于缓存查询结果而不是新插入。我有使用 VoltDB 的个人经验,我绝对推荐它(我与该公司没有任何联系)。 VoltDB 是一个内存中、横向扩展的关系数据库,针对事务工作负载进行了优化,它应该为您提供比 MongoDB 或 MySQL 高几个数量级的插入性能。它是开源的,但并非所有功能都是免费的,所以我不确定您是否需要为许可证付费。如果您不能使用 VoltDB,您可以查看 MySQL 的内存引擎或其他类似的内存引擎。

    您可以考虑的另一个优化是使用不同的数据库进行分析。最有可能的是,具有高数据摄取量的数据库在执行 OLAP 样式查询方面非常糟糕,反之亦然。回到我的建议,VoltDB 也不例外,在执行长分析查询方面也不是最佳的。这个想法是创建一个后台进程来读取前端数据库中的所有新数据(即,这将是一个 VoltDB 集群)并将其批量移动到后端数据库以进行分析(MongoDB 或更高效的东西)。然后,您可以对批量数据移动应用上述所有优化,创建一组丰富的附加索引结构以加快数据访问速度,然后运行您喜欢的分析查询并将结果保存为一组新的表/物化以供以后访问。导入/分析过程可以在后台不断重复。

    【讨论】:

    • VoltDB 看起来非常适合我们的用例。除了您提到的关于“OLAP 样式查询”的内容外,我发现了很多优点,但没有太多缺点。您还经历过或知道的任何其他缺点吗?
    • VoltDB 分析的一些限制: (1) 它没有强大的查询优化器,如果您尝试执行复杂的 SQL 查询,您将遇到严重的问题。 (2) VoltDB使用数据分区来实现并发控制(一张表是基于一个key进行分区,一个key range只被一个线程修改;一个查询执行不中断直到结束)。分析查询将运行数分钟并涉及大量数据。这实质上意味着,一旦分析查询开始执行,在查询完成之前就无法执行其他事务。
    • 值得注意的是,VoltDB 网站声称能够将数据快速导出到数据仓库:voltdb.com/products/features。我还没有看到公司声称 VoltDB 有利于分析。他们暗示有一个两层架构,其中 VoltDB 处理事务工作负载和一个专门的后端分析。
    • 忘了说:(3) VoltDB 还不支持完整的 SQL 92 标准。这意味着根本不支持某些 SQL 功能。
    • 关于实时分析,他们写道:“传统的数据库系统太慢了,无法摄取数据、实时分析并做出决策”。他们还继续谈论“智能数据”。这意味着他们很擅长,但我不清楚他们所说的“实时分析”是什么意思......
    【解决方案3】:

    表的设计通常隐含假设查询将远远超过各种 DML。因此,该表针对具有索引等的查询进行了优化。如果您有一个 DML(尤其是插入)将远远超过查询的表,那么您只需消除任何索引(包括主键)就可以走很长一段路。可以将键和索引添加到数据将被移动到并随后从中查询的表中。

    在您的 Web 应用程序前面使用 NoSQL 表来处理高插入率,然后在您闲暇时或多或少地将数据移动到标准关系数据库以进行进一步处理是一个好主意。

    【讨论】:

      猜你喜欢
      • 2011-12-24
      • 1970-01-01
      • 1970-01-01
      • 2011-08-09
      • 1970-01-01
      • 2018-06-21
      • 1970-01-01
      • 1970-01-01
      • 2020-06-29
      相关资源
      最近更新 更多