【问题标题】:Best database for high write (10000+ inserts/hour), low read (10 reads/second)?高写入(10000+ 次插入/小时)、低读取(10 次读取/秒)的最佳数据库?
【发布时间】:2009-09-13 03:03:19
【问题描述】:

我正在开发一个网络应用程序,目前正在使用 sql server 2008。但是,我正在考虑转移到另一个数据库(simpledb)以提高性能。

我有一个后台进程,每小时将多达 10000 行插入到一个特定的表中。还会读取该表以在 Web 应用程序中显示数据。当后台进程运行时,Web 应用程序不可用,因为 db 连接超时。

因此,我正在考虑迁移到亚马逊的 simpledb 以提高性能。亚马逊的 SimpleDB 是否针对此用例进行了优化?如果没有,我可以使用其他解决方案吗?

【问题讨论】:

  • 10,000 次插入/小时 = 2.7…/秒不应杀死数据库。 MySQL 和 PostgreSQL 可以轻松做到这一点。 SQL Server 应该也能做到。
  • 这就是我的想法……但我遇到了僵局。该表在插入过程中被锁定,因此 Web 应用程序停止,因为当后台进程插入数据时它无法从数据库中读取数据。
  • @rksprst:死锁可能正在发生,不是因为数据量,而是因为数据进入此表的方式。
  • 为什么每小时 10,000 次写入“高”而每小时读取 36,000 次“低”(10/秒 * 3600 秒/小时)?
  • 这是第一个问题。逐行插入是将数据放入 SQL Server 表的效率最低的方法。请参阅下面关于批量插入数据的答案。

标签: sql sql-server database performance amazon-simpledb


【解决方案1】:

您的问题是您使用的隔离级别。除非您更改它,否则 SQL Server(和许多其他数据库)会在选择将阻塞未提交读取的模式下运行。您想更改 SQL Server 使其使用 MVCC 代替(Oracle 的默认值;MySQL 和 SQL Server 也有),您的问题就会消失。

来自SET TRANSACTION ISOLATION LEVEL (Transact-SQL)

已提交阅读

指定语句不能读取 已修改但未修改的数据 由其他事务提交。这 防止脏读。数据可以 被其他交易改变 内的个别陈述 当前交易,导致 不可重复读取或幻像数据。 此选项是 SQL Server 的默认选项。

READ COMMITTED 的行为取决于 关于设置 READ_COMMITTED_SNAPSHOT 数据库 选项:

  • 如果 READ_COMMITTED_SNAPSHOT 设置为 OFF(默认),数据库引擎 使用共享锁来防止其他 来自修改行的事务同时 当前事务正在运行 读操作。 共享锁也 阻止语句读取行 被其他事务修改,直到 另一笔交易完成。 共享锁类型决定何时 它将被释放。行锁是 在下一行之前释放 处理。页面锁被释放 读取下一页时,表格 语句时释放锁 完成。
  • 如果 READ_COMMITTED_SNAPSHOT 设置为 ON,则数据库引擎使用行 版本控制以呈现每个语句 具有事务一致的 数据的快照,因为它存在于 声明的开始。锁是 不用于保护数据免受 其他交易的更新。

当 READ_COMMITTED_SNAPSHOT 数据库选项为 ON,您可以使用 READCOMMITTEDLOCK 表提示 请求共享锁定而不是行 单个语句的版本控制 在 READ 运行的事务中 COMMITTED 隔离级别。

(强调)

更改您的数据库配置以将 READ_COMMITTED_SNAPSHOT 设为 ON。

此外,尽量让您的事务保持短暂,并确保您在后台进程中提交事务(即每小时执行 10,000 次插入),因为如果它从不提交,则选择将永远阻塞(默认情况下)设置)。

【讨论】:

  • 短事务是避免阻塞的关键。
  • 理解事务和死锁对于理解关系/事务数据库的工作方式是绝对必要的。有关更多信息,请参阅:rhphost.com/SQL-standard/8277final/LiB0058.html
  • 谢谢,这似乎解决了这个问题。现在插入期间网站加载没有问题。
【解决方案2】:

正如其他人所说,您写入数据库的数据量不是问题。 SQL Server 可以轻松处理比这更多的数据。就我个人而言,我的表格每小时可以处理数十万到数百万行而没有问题,而且人们整天都在阅读这些行而没有任何减速。

  1. 您可能需要通过更改读取语句的隔离级别或使用 WITH (NOLOCK) 提示来查看脏读。

  2. 您应该考虑使用 .NET 中的批量上传对象将数据加载到数据库中。根据您在测试期间看到的性能,使用 1000-5000 批次。您需要使用数字才能获得最佳性能。与逐行插入记录相比,将数据批量插入表中会给您带来更好的性能。确保您不会在单个事务中完成整个上传。你应该每批做一个交易。

  3. 写入数据库时​​磁盘 IO 是什么样子的。

  4. 您为数据库设置了什么恢复模式?与使用 SIMPLE 恢复模式相比,数据库上的 FULL 恢复需要更多的 IO。仅当您确实需要随附的时间点恢复时才使用完全恢复。

【讨论】:

    【解决方案3】:

    每秒 3 次以下的插入不会让任何 DBMS 得到锻炼,除非每次插入操作中要插入的数据量是惊人的。同样,每秒 10 次读取不太可能对任何称职的 DBMS 造成过度压力,除非有一些您没有提到的复杂因素(例如,“读取是整个 DBMS 的聚合聚合,在一段时间后将累积数十亿条记录……嗯,前 10 亿条记录需要 100,000 小时,大约是 4,000 天,或大约 10 年”)。

    【讨论】:

      【解决方案4】:

      在跟进 Joel 的回答时,您可能需要查看为索引上的 PAD_INDEX 和 FILLFACTOR 设置适当的值。如果您没有指定这些选项,您的插入可能会在索引上进行大量重新分页,这会显着减慢您的写入时间。

      【讨论】:

        猜你喜欢
        • 2011-10-03
        • 1970-01-01
        • 2010-12-14
        • 2012-07-15
        • 2011-09-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多