我正在开发一个网络应用程序,目前正在使用 sql server 2008。但是,我正在考虑转移到另一个数据库(simpledb)以提高性能。
我有一个后台进程,每小时最多将 10000 行插入到一个特定的表中。还会读取该表以在 Web 应用程序中显示数据。当后台进程运行时,Web 应用程序不可用,因为 db 连接超时。
因此,我正在考虑转向亚马逊的 simpledb 以提高性能。亚马逊的 SimpleDB 是否针对此用例进行了优化?如果没有,我可以使用另一种解决方案吗?
我正在开发一个网络应用程序,目前正在使用 sql server 2008。但是,我正在考虑转移到另一个数据库(simpledb)以提高性能。
我有一个后台进程,每小时最多将 10000 行插入到一个特定的表中。还会读取该表以在 Web 应用程序中显示数据。当后台进程运行时,Web 应用程序不可用,因为 db 连接超时。
因此,我正在考虑转向亚马逊的 simpledb 以提高性能。亚马逊的 SimpleDB 是否针对此用例进行了优化?如果没有,我可以使用另一种解决方案吗?
您的问题是您使用的隔离级别。除非您更改它,否则 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 次插入),因为如果它从不提交,则选择将永远阻塞(在默认设置下)。
正如其他人所说,您写入数据库的数据量不是问题。SQL Server 可以轻松处理比这更多的数据。就我个人而言,我的表格每小时可以处理数十万到数百万行而没有问题,而且人们整天都在阅读这些行而没有任何减速。
您可能需要通过更改读取语句的隔离级别或使用 WITH (NOLOCK) 提示来查看脏读。
您应该考虑使用 .NET 中的批量上传对象将数据加载到数据库中。根据您在测试期间看到的性能,使用 1000-5000 批次。您需要使用数字来获得最佳性能。与逐行插入记录相比,将数据批量插入表中会给您带来更好的性能。确保您不会在单个事务中完成整个上传。你应该每批做一个交易。
当您写入数据库时,磁盘 IO 是什么样的。
你为数据库设置了什么恢复模式?与使用 SIMPLE 恢复模式相比,数据库上的 FULL 恢复需要更多的 IO。仅当您确实需要随附的时间点恢复时才使用完整恢复。
每秒插入 3 次以下不会让任何 DBMS 得到锻炼,除非每次插入操作中要插入的数据量是惊人的。同样,每秒 10 次读取不太可能对任何称职的 DBMS 造成过度压力,除非有一些您没有提到的复杂因素(例如,“读取是整个 DBMS 的聚合聚合,在一段时间后将累积数十亿条记录……嗯,前 10 亿条记录需要 100,000 小时,大约是 4,000 天,或大约 10 年”)。
在 Joel 回答的后续行动中,您可能需要查看在索引上为 PAD_INDEX 和 FILLFACTOR 设置适当的值。如果您没有指定这些选项,您的插入可能会在您的索引上进行大量重新分页,这会显着减慢您的写入时间。