小弟最近在做一个日志分析的项目,就是把源数据拿出来处理一下在放回到一个新的表中。实际数据量大概在2亿条以上,目前的测试数据有700万左右。
由于数据量过大,所以我没有一次性把数据都拿出来操作,而是用了一个Timer每次取一天的数据大概有200万左右来逐条处理。期间Timer停歇0.005秒。
但不知怎么回事处理效率越来越低,一开始的时候一秒大概能处理个10条左右的样子,可是程序运行一会以后,就变成了好几秒才能处理一条记录,并且速度越来越慢。
昨天进行了24小时的测试,结果才处理了20000多条数据,简直比人工处理还慢了。哪位大哥知道这是什么原因造成的?小弟从来没做过Oracle的操作,所以不知道问题出在哪了,Adapter 和Reader的方式我都试过了,结果都一样慢!!!
以下是Timer内的处理代码,请高手指点
 try
            {
                if ((DateTime.Now - beginDate).Minutes > 1)
                {
                    System.Diagnostics.Process.GetCurrentProcess().MinWorkingSet = new System.IntPtr(5);
                    beginDate = DateTime.Now;
                }
                if (reader.Read())
                {
                    i++;
                    string dnsname = reader.GetString(0);
                    decimal ipaddr = reader.GetDecimal(1);
                    int count = reader.GetInt32(2);
                    string SubDnsname = GetSubdomains(dnsname);
                    //string subdnsname = GetSubDomains(dnsname);
                    string ipchar = GetIPChar(ipaddr);                    //RequestAdapter.Insert(dnsname, ipaddr, TempDate.Date, count, SubDnsname, 1, ipchar);
                    OracleParameter par1 = new OracleParameter("DNSNAME", OracleType.VarChar,256);
                    par1.Value = dnsname;
                    InsertCmd.Parameters.Add(par1);                    OracleParameter par2 = new OracleParameter("IPADDR", OracleType.Number);
                    par2.Value = ipaddr;
                    InsertCmd.Parameters.Add(par2);                    OracleParameter par3 = new OracleParameter("REQUESTDATE", OracleType.DateTime);
                    par3.Value = TempDate.Date;
                    InsertCmd.Parameters.Add(par3);                    OracleParameter par4 = new OracleParameter("REQUESTCOUNT", OracleType.Number);
                    par4.Value = count;
                    InsertCmd.Parameters.Add(par4);                    OracleParameter par5 = new OracleParameter("SUBDOMAINS", OracleType.VarChar,256);
                    par5.Value = SubDnsname;
                    InsertCmd.Parameters.Add(par5);                    OracleParameter par6 = new OracleParameter("BATCH", OracleType.Number);
                    par6.Value = 1;
                    InsertCmd.Parameters.Add(par6);                    InsertCmd.ExecuteNonQuery();                                      LogBox.AppendText(DateTime.Now.ToString() + "\t第 " + i + " 条记录处理完成\n");
                    LogBox.ScrollToEnd();
                }
                else
                {
                        //修改数据库标志
                    string update = "UPDATE  DNSLOG SET  ISANALYSIS = 'Y' where REQUESTTIME>= to_date('" + TempDate.ToShortDateString() + "','yyyy/mm/dd')  AND REQUESTTIME < to_date('" + date.ToShortDateString() + "','yyyy/mm/dd')";
                    cmd.CommandText = update;
                    cmd.ExecuteNonQuery();
                    reader.Close();
                    conn.Close();
                    reader.Dispose();
                    TempDate = date;
                    System.Diagnostics.Process.GetCurrentProcess().MinWorkingSet = new System.IntPtr(5);
                        //写入日志
                    LogBox.AppendText(DateTime.Now.ToString() + "\t" + TempDate.ToShortDateString() + "日志导入完成\n");
                    if (TempDate.Date > EndDate.Date)
                    {
                        LogBox.AppendText(DateTime.Now.ToString() + "\t日志分析结束.\n");
                        string log = "=================导入日志==================\n";
                        log += "开始时间:\t" + StartDate.ToString() + "\n";
                        log += "结束时间:\t" + DateTime.Now.ToString();
                        TimeSpan span = DateTime.Now - StartDate;
                        log += "用时:\t" + span.Hours + "小时" + span.Minutes + "分钟" + span.Seconds + "秒\n";
                        log += "共导入日志:\t" + i + "条\n";
                        log += "============================================\n";
                        FileClass.SaveLog(log);
                        ImportTimer.IsEnabled = false;
                        return;
                    }
                    else
                    {
                        GetReader();
                    }
                }
                            }
            catch(Exception ex)
            {
                LogBox.AppendText(DateTime.Now.ToString()+"\ta导入失败,异常信息"+ex.Message+"\n");
                LogBox.ScrollToEnd();
            }

解决方案 »

  1.   

    为什么用read()有连接处理 怎么不用无连接的Dataset,Datatable来处理数据量大的数据。
      

  2.   

    回3楼,一开始就是用DataSet 来做查询和插入操作的,但是效率很低,就考虑改用Reader的方式处理,结果一样效率还是很低
      

  3.   

    我觉得应该是表中数据过多造成的。
    楼主可以分析一下你的 INSERT 和 UPDATE 语句的执行性能。
      

  4.   

    DataTable SQL语句优化 可以考虑从时间复杂度考虑
      

  5.   

    此外要是插入的时候费时的话,你看可不可以用事务显示的做提交。反正我有时候对.net的autocommit机制没什么信心。