【问题标题】:very slow reading of txt file using File.ReadLines in c#在 c# 中使用 File.ReadLines 读取 txt 文件的速度非常慢
【发布时间】:2016-06-26 10:37:42
【问题描述】:

我逐行读取文件并使用实体框架将此数据插入数据库。阅读速度非常慢。该文件几乎有 600 万行,我需要提高文件的读取性能。这是该文件中的单词字典,我需要将这些单词插入数据库表中。下面是该文件的几行。

390201
ТАТАМИ  NOUN,inan,neut,Fixd sing,nomn
ТАТАМИ  NOUN,inan,neut,Fixd sing,gent
ТАТАМИ  NOUN,inan,neut,Fixd sing,datv
ТАТАМИ  NOUN,inan,neut,Fixd sing,accs
ТАТАМИ  NOUN,inan,neut,Fixd sing,ablt
ТАsing,gent
ОРИГАМИ NOUN,inan,neut,Fixd ТАМИ    NOUN,inan,neut,Fixd sing,loct
ТАТАМИ  NOUN,inan,neut,Fixd plur,nomn
ТАТАМИ  NOUN,inan,neut,Fixd plur,gent
ТАТАМИ  NOUN,inan,neut,Fixd plur,datv
ТАТАМИ  NOUN,inan,neut,Fixd plur,accs
ТАТАМИ  NOUN,inan,neut,Fixd plur,ablt
ТАТАМИ  NOUN,inan,neut,Fixd plur,loct

390202
ОРИГАМИ NOUN,inan,neut,Fixd sing,nomn
ОРИГАМИ NOUN,inan,neut,Fixd sing,datv
ОРИГАМИ NOUN,inan,neut,Fixd sing,accs
ОРИГАМИ NOUN,inan,neut,Fixd sing,ablt
ОРИГАМИ NOUN,inan,neut,Fixd sing,loct
ОРИГАМИ NOUN,inan,neut,Fixd plur,nomn
ОРИГАМИ NOUN,inan,neut,Fixd plur,gent
ОРИГАМИ NOUN,inan,neut,Fixd plur,datv
ОРИГАМИ NOUN,inan,neut,Fixd plur,accs

我解析该文件的代码如下:

public static void parseFileFromToSegment(int beginId, int endId)
    {
    using (var db = new Context())
    {
        string theWordFromFile;
        string wordData;
        int wordIdFromFile = 1;
        int tempWordId;

        IEnumerable<string> allFileLines = File.ReadLines(fileName);
        allFileLines = allFileLines.SkipWhile(n => n != beginId.ToString());
        foreach (string line in allFileLines)
        {
            if (string.IsNullOrEmpty(line))
                continue;
            if (!string.IsNullOrEmpty(line) && Int32.TryParse(line, out tempWordId))
            {
                if (tempWordId < beginId)
                {
                    continue;
                }
                if (tempWordId > endId) 
                    break;

                wordIdFromFile = tempWordId;
                if (wordIdFromFile % 100 == 0)
                    Console.WriteLine("Current id - " + wordIdFromFile);
                continue;
            }

            theWordFromFile = line.Substring(0, line.IndexOf('\t'));
            wordData = line.Substring(line.IndexOf('\t')).Trim();
            TheWord theWord = new TheWord { WordFormId = wordIdFromFile, word = theWordFromFile, word_form_data = wordData };

            db.TheWords.Add(theWord);
        }
        db.SaveChanges();
        Console.WriteLine("saved");
    }
}

所以阅读速度很慢。我可以做些什么来提高性能?谢谢

【问题讨论】:

  • 您确定性能下降不是因为在单个 SaveChanges() 中向 EF 添加了 600 万条记录吗?
  • @SimonKarlsson 他已经在这样做了。 File.ReadLines 返回一个 IEnumerable&lt;string&gt; 并在下面使用 StreamReader.ReadLine()
  • 这块!string.IsNullOrEmpty(line) &amp;&amp; 没用。您之前已经检查了相反的行。但它不会改变速度
  • 尝试在循环内调用SaveChanges() - 当然不是每次迭代都如此。您可以保存每 1000 行
  • @Alexander Derck 你说得对,谢谢。我为“theWord”对象创建了一个 List 并使用 List.AddRange(list with theWord objects) 方法 - 问题已解决 - 它是在检测 EF 的变化。

标签: c# file readlines


【解决方案1】:

不是文件读取速度慢。这是数据库插入。

您可以使用带有 DataAdapter 的纯 ADO.NET 来插入行 (using batching) 或 SQLBulkCopy 类 (example)。

【讨论】:

  • savechanges 不是问题 - 在读取 20 000 行后,将在此方法中完成保存。但是它们的阅读量非常小。当它们被读取时,EF 工作正常 - 非常快速地保存它们
  • 这很容易测试。只需注释掉所有实体框架代码并再次运行示例。速度快吗?
  • 我评论了 - 它仍然运行得很慢。读取整个文件需要很多小时(20-30)
  • 没有数据库代码吗?我不在乎SaveChanges()。您是否在没有所有数据库代码的情况下对其进行了测试?因为数据库插入不太可能比文件读取快,除非文件是通过非常慢的网络共享读取的。
  • @AlexeyRumin 作为未来的建议:同一个文件(实际上是同一个物理磁盘)上的 I/O 绑定进程永远不会通过多线程变得更好。 CPU 绑定的进程可能。
【解决方案2】:

阅读所有 cmets,您似乎每 20.000 个“id”调用一次 parseFileFromToSegment,这可能(根据您的示例文本)每个 id 有很多行。

所以你打电话给你的parseFileFromToSegment 并这样做:

IEnumerable<string> allFileLines = File.ReadLines(fileName);
allFileLines = allFileLines.SkipWhile(n => n != beginId.ToString());

在每次调用时:从一开始就读取,每次调用时可能会在文件中读取数百万行。

尝试只调用一次,看看它是否更快,如果你想批量保存每 'n' 条记录,然后这样做,不要在每次迭代时打开并读取整个文件 [可能]的'n'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-15
    • 2010-11-25
    • 2014-06-22
    • 1970-01-01
    • 1970-01-01
    • 2016-05-21
    • 2017-07-23
    • 2021-10-12
    相关资源
    最近更新 更多