【问题标题】:Importing CSV to SQL-Server - Performance将 CSV 导入 SQL-Server - 性能
【发布时间】:2014-10-29 09:12:47
【问题描述】:

我创建了一个小项目,它允许用户通过实体框架将 CSV 文件导入 SQL。主要过程如下所示:

using (TextFieldParser tx = new TextFieldParser(file, Encoding.UTF8))
        { 
            tx.TextFieldType = FieldType.Delimited;
            tx.SetDelimiters(";");
            tx.ReadLine(); //The First Line are the headers, no need

            while (!tx.EndOfData)
            {
                decimal decTmp;
                int intTmp;

                string[] fields = tx.ReadFields();

                //Convert every field to the appropriate type, tryparse if nullable
                ReportInfo("Verarbeite Nummer: " + fields[(int)ConnectionEvaluationFileField.PhoneNumber].Trim());

                Verbindunganalyse con = new Verbindunganalyse();
                con.Auswertungszeitraum = fields[(int)ConnectionEvaluationFileField.EvaluationTimeSpan].TrimStart('0');
                con.Betrag_inkl_MWST_CHF = Decimal.Parse(fields[(int)ConnectionEvaluationFileField.Cost]);
                if (decimal.TryParse(fields[(int)ConnectionEvaluationFileField.DataInMb], out decTmp))
                    con.Daten_MB = decTmp;
                con.Durchwahlnummer = Int64.Parse(fields[(int)ConnectionEvaluationFileField.PhoneNumber]);
                con.Produkteigenschaft = fields[(int)ConnectionEvaluationFileField.ProductProperty];
                if (Int32.TryParse(fields[(int)ConnectionEvaluationFileField.Messages], out intTmp))
                    con.SMS_MMS_Anzahl = intTmp;
                con.TelefonieDauer = TimeSpan.Parse(fields[(int)ConnectionEvaluationFileField.CallLength]);

                con.Untergruppe = fields[(int)ConnectionEvaluationFileField.SubGroup];

                if (Int32.TryParse(fields[(int)ConnectionEvaluationFileField.Connections], out intTmp))
                    con.Verbindungen_Anzahl = intTmp;

                container.Verbindunganalyse.Add(con);
            }
        }

这是德语,但我认为代码很清楚:我使用 TextFieldParser 读取数据,创建一个新实体并将字段解析/检查到属性中。

问题:客户曾经有一个访问解决方案,导入数据需要大约 20-30 秒,而我的解决方案需要大约 2-3 分钟来导入 2 个文件和 5k 个数据集。

我发现了一些像 https://efbulkinsert.codeplex.com/ 这样的 BulkInsert,但我们在这里谈论的是两个文件中的 10k 数据集。

我删除了 ReportInfo 等,但我看不到让这项工作更快的方法。您是否认为有可能使用 EF 更快地制作这些东西?还是 TextFieldParser 太慢了,我需要在那里检查一下?

【问题讨论】:

  • 你知道哪个部分慢吗?它是通过文本文件的循环吗?它是插入实体框架吗?如果是后者,那么使用 BulkInsert 并绕过 EntityFramework 可能会更好。
  • 好吧,没有数据集需要超过几毫秒,问题是,Access 可以轻松地批量插入 SQL。我们的任务是与之抗争。它可能会更慢,但不仅仅是 10 倍
  • 批量插入在 SQL Server 中非常有效:msdn.microsoft.com/en-us/library/ms188365.aspx
  • 尝试在您的上下文 Configuration.AutoDetectChangesEnabled = falseConfiguration.ValidateOnSaveEnabled = false 上设置这些标志。或者,您可以使用 SqlBulkCopy 而不是 EF 来插入数据。
  • ZerO,您的想法 Configs 帮了大忙,它使程序从 2-3 分钟运行到 30-40 秒。如果你把它写成答案,我会说这是一个答案,也是一个很好的步骤

标签: c# sql entity-framework csv


【解决方案1】:

我知道这是一篇旧帖子,但我自己一直在尝试。我使用以下代码尝试了Entity Framework Seeder NuGet packagebare-metal SQL bulk insert

CREATE TABLE [dbo].[TempTable] (
    [Field] type constraints,
    etc...
)
GO
BULK INSERT TempTable FROM 'filePath' WITH (
    FIRSTROW = 2,
    FIELDTERMINATOR = ',',
    ROWTERMINATOR = '\r\n'
)
GO
INSERT INTO [FinalTable] SELECT [Fields] FROM [TempTable]
GO
DROP TABLE [TempTable]

播种方法在 67 秒内插入 10,000 条记录,批量插入方法需要 223 毫秒。这真的很简单。

【讨论】:

    猜你喜欢
    • 2021-02-04
    • 2012-04-05
    • 1970-01-01
    • 2013-02-20
    • 2013-10-08
    • 1970-01-01
    • 1970-01-01
    • 2012-03-13
    相关资源
    最近更新 更多