使用C#处理文件的最佳实践

4

我所负责的应用程序在15分钟内会生成数百个文件(csv格式),应用程序的后端会将这些文件进行处理(使用这些值更新数据库)。其中一个问题是数据库锁。

如何处理数千个文件以避免锁定并高效地处理这些文件?

创建单个文件并对其进行处理是否更为高效?还是逐个处理单个文件更好?

有哪些常见的最佳实践方法?

编辑:数据库不是关系型DBMS,而是NoSQL、面向对象的内存数据库。


这个应用程序是否只运行了一个实例?您是否在多个线程上执行数据库操作? - Adam Robinson
有几个服务器运行着相同的应用程序,并且它们正在生成文件。 - DarthVader
2
“数据库锁定”究竟有什么问题? - Paolo
好的,更新会锁定数据库。 - DarthVader
正在创建哪种类型的文件? - Mark Pearl
显示剩余2条评论
6个回答

3
假设您有N台机器创建文件,并且每个文件都类似,通常被消耗到数据库中的相同表中... 我建议设置一个队列,让所有机器将其文件写入队列,然后在另一侧有一个东西从队列中取出内容并将其处理到数据库中。因此,一次处理一个文件。您甚至可以通过直接写入队列来优化文件操作。

我已经有这样的方案了,但我担心会出现一些争用。 - DarthVader
@user177883:是什么类型的争用?这种方案应该能够缓解任何数据库锁定。是否存在性能问题或类似情况? - Jacob G
如果文件数量超过了处理能力怎么办?假设你每天有十亿个页面浏览量,每个页面浏览都需要处理一些数据。我想你的答案可能是增加更多服务器从队列中提取更多数据。 - DarthVader
那么,另一种选择就是重构您的数据库或生成的文件,以避免锁定,从而可以进行更多的并发处理。例如,如果您有N个操作要在表上执行,如果x个操作是插入操作,y个操作是更新操作,那么您可能可以并行处理插入操作,然后串行处理更新操作。但是,如果您谈论的是数十亿的页面浏览量,那么我们确实需要更多关于您的文件和数据库的信息来减轻锁定并确保性能。 - Jacob G
我的数据库中没有表,面向对象的,完全在内存中运行。 - DarthVader
我要在这里宣称无知...你在使用什么产品?Cassandra或类似的产品吗?我认为nosql解决方案最小化了像锁和事务之类的东西。 - Jacob G

2

如果您在使用锁时遇到问题,很可能是更新的数据库表没有适当的索引。获取执行更新操作的SQL代码,并查找其执行计划;如果您正在使用MSSQL,则可以在SSMS中执行此操作;如果UPDATE操作导致表扫描,则需要添加一个索引来帮助隔离被更新的记录(除非您正在更新表中的每个记录;那可能会有问题)。


1
如果我使用一种仅在内存中工作的NoSQL面向对象数据库,会怎样呢? - DarthVader

1

鉴于我对您的具体情况了解有限...

就性能而言,关闭文件可能是您在时间方面执行的最昂贵的操作,因此我的建议是,如果您可以采用单个文件路线,则这将是最高效的方法。


在这个方案中,你会怎么做? - DarthVader

0

锁定将保护文件,直到第一个文件处理完成。

class ThreadSafe
{
  static readonly object _locker = new object();
  static int _val1, _val2;

  static void Go()
  {
    lock (_locker)
    {
      if (_val2 != 0) Console.WriteLine (_val1 / _val2);
      _val2 = 0;
    }
  }
}

0
听起来你可能需要一个单文件机制,或者将所有文件都放在一个共享的单个目录中,该目录不断检查最旧的csv文件并将其通过你的代码运行。这可能是“最便宜”的解决方案。如果你实际上正在生成更多的文件而无法处理,那么我可能会重新考虑整个系统架构,而不是采用“临时措施”的方法。

0

你可以尝试在应用程序代码层面解决并发问题,并强制 DBMS 在更新期间不锁定对象。

(在关系型数据库中,您可以设置最低的事务隔离级别(读未提交))

如果可以这样做,另一个选项是截断所有旧对象并批量插入新值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接