在我的应用中,用户输入了一些内容,我想在用户输入时自动保存。保存调用不适用于每次击键,而是仅在用户暂停超过200ms时进行自动保存。所以在一个典型的段落中有15-20个服务器调用。内容不会经常读取,所以我需要优化写入。
由于遗留代码原因,我必须在MSSQL Server上保存数据。我在负载测试中得到10秒的平均响应时间。如何提高性能?
我考虑的一种方法是不是直接在mssql中保存数据,而是将其保存在Cassandra或redis中,然后最终(可能是以规则的时间间隔)将其写入mssql。
另一种方法是不进行频繁更新,而是为每次自动保存插入新记录。然后,后台进程将每隔几分钟清除除最新记录之外的所有记录。
更新: 我用2个表的简单更新调用替换了现有的逻辑,现在我看到了改进。存储过程很长,在负载下需要10秒钟。所以我现在坚持这个问题。我仍然想知道我可以在应用程序服务器层上做些什么来减少频繁的数据库调用。
答案 0 :(得分:1)
很难直接回答您的问题,但这里有一些基于我们在多个活跃用户情况下所做的提示。
如果您正在每次击键时写入/触发,请将击键传递给后台线程,并且在阻止用户键入时不要执行数据库写入或任何网络调用。快速打字员可以达到每秒20次击键,你不能引入延迟。
如果在网页上录制,您可以使用localStorage。不要在每次击键时发出AJAX样式调用,因为未完成的请求有限制。您需要实现某种缓冲发送。请记住,现实世界中的网络呼叫只能通过网络进行300mS的扩展。
你真的需要保存每次按键,还是每N秒都可以接受?每个保存操作最终都会变成磁盘操作,因此您确实希望合并尽可能多的保存。做最快的方法就是不要这样做。
如果要录制到数据库,那么更新现有行通常会更快,如果您可以先通过直接键获取它。不幸的是,有时可以更快地插入新行并稍后清理多余的行。如果表的索引很少,这往往是真的。哪个更快取决于使用的数据库引擎及其使用方式。我们使用这两种方法。
使用数据库时请记住,他们经常会保留某种类型的日记,因此如果您经常更新,可能会对日记文件造成很大的负担。
如果您正在使用fopen等技术(使用C术语),那么fwrite可以很好地执行,但如果您担心系统故障恢复,则可能需要调用fsync,这会限制您的最高性能速率。如果你需要fsync,数据库可能会更好。
您可能会考虑非常频繁地写入事务日志表,然后每隔N秒发布到实际存储。例如,如果我输入客户名称,我可能会将每个击键记录到一个键盘记录表中,然后让后台作业读取键盘记录表并将数据传输到customers表。这有助于减少对customers表的操作,同时还允许将keylog表优化为记录击键。但是,代价是更多的代码服务器端。
总的来说,你想要像这样的逻辑
关键字处理程序
后台主题
请记住上面的用户可以输入并立即点击关闭,因此您的最终缓冲区写入可能尚未刷新。你需要处理这个问题。
如果您认为这是正确的,用户将不会注意到任何延迟。在我们的使用中,我们平均记录大约1000次击键/秒,所有这些都通过专用网络路由到中心点。这种负载几乎不会出现问题,甚至网络监控也看不到这么少的流量。 祝你好运。