Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.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#_Loops_Datatable - Fatal编程技术网

C#:遍历一个巨大的数据表

C#:遍历一个巨大的数据表,c#,loops,datatable,C#,Loops,Datatable,使用for循环遍历包含大约40000条记录的数据表几乎需要4分钟。在循环中,我只是读取每行特定列的值,并将其浓缩为字符串 我没有打开任何数据库连接或其他东西,因为它是一个函数,接收一个数据表,遍历它并返回一个字符串 有没有更快的方法 代码如下: private string getListOfFileNames(Datatable listWithFileNames) { string whereClause = ""; if (l

使用for循环遍历包含大约40000条记录的数据表几乎需要4分钟。在循环中,我只是读取每行特定列的值,并将其浓缩为字符串

我没有打开任何数据库连接或其他东西,因为它是一个函数,接收一个数据表,遍历它并返回一个字符串

有没有更快的方法

代码如下:

   private string getListOfFileNames(Datatable listWithFileNames)
   {     
        string whereClause = "";

            if (listWithFileNames.Columns.Contains("Filename"))
            {
                whereClause = "where filename in (";
                for (int j = 0; j < listWithFileNames.Rows.Count; j++)
                    whereClause += " '" + listWithFileNames.Rows[j]["Filename"].ToString() + "',";
            }
            whereClause = whereClause.Remove(whereClause.Length - 1, 1);
            whereClause += ")";    

        return whereClause;                
    }    
私有字符串getListOfFileNames(带有文件名的数据表列表)
{     
字符串whereClause=“”;
if(listWithFileNames.Columns.Contains(“文件名”))
{
whereClause=“where filename in(”;
对于(int j=0;j
以下linq语句在变量的第一列上有where子句,在第三列上有concat子句

 string CSVValues = String.Join(",", dtOutput.AsEnumerable()
                                                .Where(a => a[0].ToString() == value)
                                                .Select(b => b[2].ToString()));
  • 您是否使用StringBuilder来连接字符串,而不仅仅是常规的字符串连接
  • 你真的需要从数据库中提取更多的列吗?如果是这样,尽量不要这样做。仅向后拉所需的立柱
  • 您是否要从数据库中提取更多行,然后您真的需要这样做?如果是这样,尽量不要这样做。仅向后拉您需要的行
  • 这台计算机有多少内存?当你运行程序或接近它时,它是否达到最大值?处理器是否处于最大值?如果您使用的内存太多,则可能需要进行更多的流式处理。这意味着不将整个结果集拉入内存(即数据表),而是一次读取一行。这也可能意味着,您可能需要将结果附加到文件中,以避免占用太多内存,而不是将结果合并到字符串(或StringBuilder)中

  • 第1步-通过分析器运行它,确保在优化时看到正确的东西

    举个例子,我们确信有一个问题是数据库交互缓慢,当我们运行探查器时,数据库几乎没有出现

    也就是说,可能的尝试:

    • 如果内存可用,请将查询转换为列表,如下所示 将强制读取完整的数据库。否则linq可能会加载 执行多个db查询的块
    • 将工作推送到数据库-如果可以创建查询,则向下修剪 您正在查看的数据,甚至为您计算字符串, 那可能更快
    • 如果查询经常运行,但数据很少运行 更改,考虑将数据复制到本地数据库(如SQLite) 您正在使用远程数据库
    • 如果您使用的是本地sql server,请尝试使用sqlite,它会更快 很多事情
    var值=数据表
    .可计算的()
    .Select(row=>row.Field(“columnName”);
    var colValueStr=string.join(“,”,value.ToArray());
    
    尝试使用表达式在表中添加虚拟列。大概是这样的:

    DataColumn dynColumn = new DataColumn();
    
    {
        dynColumn.ColumnName = "FullName";
        dynColumn.DataType = System.Type.GetType("System.String");
        dynColumn.Expression = "LastName+' '-ABC";
    }
    UserDataSet.Tables(0).Columns.Add(dynColumn);
    

    在以后的代码中,您可以改用这个伪列。您不需要旋转任何循环来连接字符串。

    尝试使用并行for循环。。 下面是示例代码

    Parallel.ForEach(dataTable.AsEnumerable(),
                item => { str += ((item as DataRow)["ColumnName"]).ToString(); });
    

    我把工作分成了小块,让每一块都由自己的线程处理。您可以通过改变线程数来微调线程数。尝试使用不同的数字,这样您就可以看到性能上的差异

    private string getListOfFileNames(DataTable listWithFileNames)
    {
        string whereClause = String.Empty;
    
        if (listWithFileNames.Columns.Contains("Filename"))
        {
            int nthreads = 8; // You can play with this parameter to fine tune and get your best time.
            int load = listWithFileNames.Rows.Count / nthreads; // This will tell how many items reach thread mush process.
    
            List<ManualResetEvent> mres = new List<ManualResetEvent>(); // This guys will help the method to know when the work is done.
            List<StringBuilder> sbuilders = new List<StringBuilder>(); // This will be used to concatenate each bis string.
    
            for (int i = 0; i < nthreads; i++)
            {
                sbuilders.Add(new StringBuilder()); // Create a new string builder
                mres.Add(new ManualResetEvent(false)); // Create a not singaled ManualResetEvent.
    
                if (i == 0) // We know were to put the very begining of your where clause
                {
                    sbuilders[0].Append("where filename in (");
                }
    
                // Calculate the last item to be processed by the current thread
                int end = i == (nthreads - 1) ? listWithFileNames.Rows.Count : i * load + load;
    
                // Create a new thread to deal with a part of the big table.
                Thread t = new Thread(new ParameterizedThreadStart((x) =>
                {
                    // This is the inside of the thread, we must unbox the parameters
                    object[] vars = x as object[];
                    int lIndex = (int)vars[0];
                    int uIndex = (int)vars[1];
                    ManualResetEvent ev = vars[2] as ManualResetEvent;
                    StringBuilder sb = vars[3] as StringBuilder;
                    bool coma = false;
    
                    // Concatenate the rows in the string builder
                    for (int j = lIndex; j < uIndex; j++)
                    {
                        if (coma)
                        {
                            sb.Append(", ");
                        }
                        else
                        {
                            coma = true;
                        }
    
                        sb.Append("'").Append(listWithFileNames.Rows[j]["Filename"]).Append("'");
                    }
    
                    // Tell the parent Thread that your job is done.
                    ev.Set();
                }));
    
                // Start the thread with the calculated params
                t.Start(new object[] { i * load, end, mres[i], sbuilders[i] });
            }
    
            // Wait for all child threads to finish their job
            WaitHandle.WaitAll(mres.ToArray());
    
            // Concatenate the big string.
            for (int i = 1; i < nthreads; i++)
            {
                sbuilders[0].Append(", ").Append(sbuilders[i]);
            }
    
            sbuilders[0].Append(")"); // Close your where clause
    
            // Return the finished where clause
            return sbuilders[0].ToString();
        }
    
        // Returns empty
        return whereClause;
    }
    
    私有字符串getListOfFileNames(带有文件名的数据表列表)
    {
    string whereClause=string.Empty;
    if(listWithFileNames.Columns.Contains(“文件名”))
    {
    int nthreads=8;//您可以使用此参数进行微调并获得最佳时间。
    int load=listWithFileNames.Rows.Count/nthreads;//这将告诉有多少项到达了线程mush进程。
    List mres=new List();//这些人将帮助方法知道工作何时完成。
    List sbuilders=new List();//这将用于连接每个bis字符串。
    对于(int i=0;i
    {
    //这是线程的内部,我们必须取消绑定参数
    对象[]变量=x作为对象[];
    int-lIndex=(int)vars[0];
    int uIndex=(int)vars[1];
    ManualResetEvent ev=vars[2]作为ManualResetEvent;
    StringBuilder sb=vars[3]作为StringBuilder;
    布尔昏迷=假;
    //连接字符串生成器中的行
    对于(int j=lIndex;jprivate string getListOfFileNames(DataTable listWithFileNames)
    {
        string whereClause = String.Empty;
    
        if (listWithFileNames.Columns.Contains("Filename"))
        {
            int nthreads = 8; // You can play with this parameter to fine tune and get your best time.
            int load = listWithFileNames.Rows.Count / nthreads; // This will tell how many items reach thread mush process.
    
            List<ManualResetEvent> mres = new List<ManualResetEvent>(); // This guys will help the method to know when the work is done.
            List<StringBuilder> sbuilders = new List<StringBuilder>(); // This will be used to concatenate each bis string.
    
            for (int i = 0; i < nthreads; i++)
            {
                sbuilders.Add(new StringBuilder()); // Create a new string builder
                mres.Add(new ManualResetEvent(false)); // Create a not singaled ManualResetEvent.
    
                if (i == 0) // We know were to put the very begining of your where clause
                {
                    sbuilders[0].Append("where filename in (");
                }
    
                // Calculate the last item to be processed by the current thread
                int end = i == (nthreads - 1) ? listWithFileNames.Rows.Count : i * load + load;
    
                // Create a new thread to deal with a part of the big table.
                Thread t = new Thread(new ParameterizedThreadStart((x) =>
                {
                    // This is the inside of the thread, we must unbox the parameters
                    object[] vars = x as object[];
                    int lIndex = (int)vars[0];
                    int uIndex = (int)vars[1];
                    ManualResetEvent ev = vars[2] as ManualResetEvent;
                    StringBuilder sb = vars[3] as StringBuilder;
                    bool coma = false;
    
                    // Concatenate the rows in the string builder
                    for (int j = lIndex; j < uIndex; j++)
                    {
                        if (coma)
                        {
                            sb.Append(", ");
                        }
                        else
                        {
                            coma = true;
                        }
    
                        sb.Append("'").Append(listWithFileNames.Rows[j]["Filename"]).Append("'");
                    }
    
                    // Tell the parent Thread that your job is done.
                    ev.Set();
                }));
    
                // Start the thread with the calculated params
                t.Start(new object[] { i * load, end, mres[i], sbuilders[i] });
            }
    
            // Wait for all child threads to finish their job
            WaitHandle.WaitAll(mres.ToArray());
    
            // Concatenate the big string.
            for (int i = 1; i < nthreads; i++)
            {
                sbuilders[0].Append(", ").Append(sbuilders[i]);
            }
    
            sbuilders[0].Append(")"); // Close your where clause
    
            // Return the finished where clause
            return sbuilders[0].ToString();
        }
    
        // Returns empty
        return whereClause;
    }