Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/85.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c#推进数据库的速度非常慢_C#_Sql_Sql Server 2008_Sqlcommand - Fatal编程技术网

c#推进数据库的速度非常慢

c#推进数据库的速度非常慢,c#,sql,sql-server-2008,sqlcommand,C#,Sql,Sql Server 2008,Sqlcommand,我正在制作一个文件夹/文本文件阅读器。应将获取的数据推送到SQL server。然而,事情真的,真的。。慢点 真慢=> 需要插入的数据: 2.73 GB(2938952122字节) 蔓延 78995个文件,5908个文件夹 文件夹结构为 文件夹(顶级) 文件夹 文件夹 文本文件 更多文件夹->可能100个 文件夹 文件夹 文本文件 共60个文件夹 。。。 我已经读了大约3天了 此外,由于文件包含大量重复值,我认为速度也很慢 我认为发生这种情况的原因: 因为我有一个关

我正在制作一个文件夹/文本文件阅读器。应将获取的数据推送到SQL server。然而,事情真的,真的。。慢点

真慢=>

需要插入的数据:

2.73 GB(2938952122字节)

蔓延

78995个文件,5908个文件夹

文件夹结构为

文件夹(顶级)

  • 文件夹
    • 文件夹
    • 文本文件
    • 更多文件夹->可能100个
  • 文件夹
    • 文件夹
    • 文本文件
  • 共60个文件夹
    • 。。。
我已经读了大约3天了

此外,由于文件包含大量重复值,我认为速度也很慢

我认为发生这种情况的原因:

  • 因为我有一个关系数据库,所以我需要不断打开一个新的连接
  • 嵌套foreach

    • 有没有办法提高这种戏剧性的表现
    • 我应该改用SQLbatchcopy吗?您甚至可以将其用于关系表,因为我看到的所有示例都只填充了一个表,而忽略了需要插入的外键(我的get是通过SQL db中的自动增量生成的)
    • 有没有可能有另一种解决方案可以让这更容易
  • 源代码:

      static void leesTxt(string rapport, string TreinNaam)
                        {
                            foreach (string textFilePath in Directory.EnumerateFiles(rapport, "*.txt"))
                            {
    
                                string textname = Path.GetFileName(textFilePath);
                                textname = textname.Substring(0, textname.Length - 4);
                                List<string> variablen = new List<string>();
    
    
                                using (StreamReader r = new StreamReader(textFilePath))
                                {
                                    for (int x = 0; x <= 10; x++)
                                        r.ReadLine();
    
                                    string output;
    
                                    while (true)
                                    {
    
                                        output = r.ReadLine();
                                        if (output == null)
                                            break;
    
                                        if (Regex.IsMatch(output, @"^\d"))
                                        {
                                                variablen.Clear();
                                                string[] info = output.Split(' ');
                                                int kolom = 6;
                                                datum = info[0];
    
    
    
    
    
                                            string[] datumTijdelijk = datum.Split(new[] { '/' });
    
                                            try
                                            {
                                                datum = string.Format("{2}/{1}/{0}", 
                                            }
                                            catch
                                            {
                                                datum = "0002/02/02";
                                            }
    
    
                                            try
                                            {
                                                tijd = info[1];
                                            }
                                            catch
                                            {
                                                Debug.WriteLine(tijd);
                                                tijd = "00:00:00.000";
                                            }
                                            try
                                            {
                                                foutcode = info[2];
                                                absentOfPresent = info[4];
                                                teller = info[5];
                                                omschrijving = info[6];
                                            }
                                            catch
                                            {
    
                                            }
    
    
                                            while (kolom < info.Count() - 1)
                                            {
                                                kolom++;
                                                omschrijving = omschrijving + " " + info[kolom];
                                            }
                                            PushFoutenToSQLdb(datum, tijd, foutcode, textname, omschrijving, teller, absentOfPresent, TreinNaam);
                                        }
                                        if (output == string.Empty)
                                        {
                                            output = " ";
                                        }
                                        if (Char.IsLetter(output[0]))
                                        {
                                            if (variablen.Contains(output))
                                                output = output + "*";
    
                                            try
                                            {
                                                PushExtraInfoToSQLdb(output, datum, tijd, foutcode, textname, teller, absentOfPresent, omschrijving, TreinNaam);
                                            }
                                            catch (Exception ex)
                                            {
                                            }
    
                                            variablen.Add(output);
                                        }
    
                                    }
    
    
    
                                   }  
    static void PushExtraInfoToSQLdb(string waarde, string datum, string tijd, string foutcode, string module, string teller, string Mnemo, string omschrijving, string treinNaam)
                    {
                        myCommand = new SqlCommand("INSERT INTO [Events].[dbo].[ExtraInfo] (Value,FoutId) Values (@waarde,(SELECT FoutId from [Events].[dbo].[Fouten] WHERE Datum = @datum AND Time = @tijd AND FoutCode = @foutcode AND TreinId = (SELECT TreinId from [Events].[dbo].[Treinen] WHERE Name = @treinNaam)))", myConnection);
                        myCommand.Parameters.AddWithValue("@waarde", waarde);
                        myCommand.Parameters.AddWithValue("@datum", datum);
                        myCommand.Parameters.AddWithValue("@tijd", tijd);
                        myCommand.Parameters.AddWithValue("@foutcode", foutcode);
                        myCommand.Parameters.AddWithValue("@module", module);
                        myCommand.Parameters.AddWithValue("@teller", teller);
                        myCommand.Parameters.AddWithValue("@Mnemo", Mnemo);
                        myCommand.Parameters.AddWithValue("@omschrijving", omschrijving);
                        myCommand.Parameters.AddWithValue("@treinNaam", treinNaam);
    
    
                        try
                        {
                            myCommand.ExecuteNonQuery();
                        }
                        catch (Exception ex)
                        {
                        }
    
                    } 
    static void PushFoutenToSQLdb(string datum, string tijd, string foutcode, string module, string omschrijving, string teller, string absentPresent, string treinNaam)
                        {
                            myCommand = new SqlCommand("INSERT INTO [Events].[dbo].[Fouten]  (Datum ,FoutCode, Omschrijving, Module,Time,Teller,Mnemo, TreinId)  Values (@datum , @foutcode, @omschrijving, @module, @tijd, @teller, @absentPresent ,(SELECT TreinId from [Events].[dbo].[Treinen] WHERE Name = @treinNaam))", myConnection);
                            myCommand.Parameters.AddWithValue("@datum", datum);
                            myCommand.Parameters.AddWithValue("@tijd", tijd);
                            myCommand.Parameters.AddWithValue("@foutcode", foutcode);
                            myCommand.Parameters.AddWithValue("@module", module);
                            myCommand.Parameters.AddWithValue("@teller", teller);
                            myCommand.Parameters.AddWithValue("@omschrijving", omschrijving);
                            myCommand.Parameters.AddWithValue("@absentPresent", absentPresent);
                        myCommand.Parameters.AddWithValue("@treinNaam", treinNaam);
    
                        try
                        {
                            myCommand.ExecuteNonQuery();
                        }
                        catch (Exception ex)
                        {
    
                        }
                    }
    
    static void leesTxt(字符串关系,字符串树)
    {
    foreach(Directory.EnumerateFiles(report,*.txt)中的字符串textFilePath)
    {
    字符串textname=Path.GetFileName(textFilePath);
    textname=textname.Substring(0,textname.Length-4);
    List variablen=新列表();
    使用(StreamReader r=newstreamreader(textFilePath))
    {
    
    对于(int x=0;x,因为这些都是插入,而且正如每个人都指出的,逐行插入不是一个好方法。请查看。这是为了在考虑性能的情况下直接从代码将批/批量插入写入数据库而设计的

    文件摘录

    Microsoft SQL Server包含一个名为bcp的流行命令提示实用程序,用于将数据从一个表移动到另一个表,无论是在单个服务器上还是在服务器之间。SqlBulkCopy类允许您编写提供类似功能的托管代码解决方案。还有其他方法可以将数据加载到SQL Server表中(例如,插入语句),但SqlBulkCopy比它们具有显著的性能优势。

    最好的方法(因为数据来自文本文件)可能是创建内存中的
    DataTable
    ,然后在其中定义与数据库架构匹配的架构。然后使用要插入的数据填充此表,并调用
    WriteToServer
    方法并传入该表

    由于
    SqlBulkCopy
    仅支持每个实例写入1个表,因此您必须执行2次,一次用于
    Fouten
    表,一次用于
    ExtraInfo
    表。在使用现有
    INSE中的
    SELECT
    语句时,您还必须先提取一些信息RT
    语句,在将数据表传递给
    SqlBulkCopy
    实例之前,可以使用该语句填充
    DataTable
    SqlBulkCopy
    也不适用于
    事务
    ,因此在插入数据之前必须先对其进行sanatize处理,因为如果存在验证,则无法轻松回滚所有内容一条或多条记录上的错误

    伪码
  • 创建一个key=
    TreinId
    和value=
    Name
    的内存字典,并使用
    DataReader
    从现有数据填充它
  • Fouten
    创建与
    Fouten
    表架构匹配的数据表
  • 使用文本文件中的数据填充表格,并使用步骤1中为
    TreinId创建的字典
  • 调用
    SqlBulkCopy
    ,上传数据
  • 创建一个key=Date+Time+FoutCode+TreinNaam,value=FoutId的内存字典,使用
    DataReader
    从现有(新)数据填充它。看起来这有点复杂,也许有更好的方法来定义此查找
  • 使用文本文件中的数据填充
    ExtraInfo
    表,并使用步骤5中创建的字典将FK值返回到
    Fouten
  • 调用
    SqlBulkCopy
    ,上传数据
  • 现有结构的其他注意事项
  • 运行并查看是否有其他因素导致您不知道的缓慢插入(例如插入中的未调优SELECT语句)。如果您看到定义的单个插入语句非常昂贵,则执行上述
    SqlBulkCopy
    几乎没有影响
  • 正如您在注释中所指出的,您的表很大。在INSERT语句中,您一次执行一个SELECT语句,同时也为每个语句执行一个SELECT。如果您的索引定义不正确,则可能会对每个INSERT中的每个SELECT语句执行表扫描。这将导致巨大的性能损失。最佳修复方法如下:
  • 通过缓存字典中内存中可能的值列表,从插入中删除select。使用DataReader完成此操作
  • 调整索引以确保它们在
    SELECT
    语句的
    INSERT
    部分中使用
  • 确保在INSERT命令中定义的数据与架构中的数据类型完全匹配。例如:如果您有一个NVARCHAR列,但将该类型定义为VARCHAR,则可能需要更长的时间,或者数据库中有一个BIGINT