0

我有一个超过一百万行的 .DBF 文件(嗯,6 个具有相同结构的 DBF 文件)。我还有一个 C# 应用程序,它使用我们制作的 API 将这些数据迁移到 SQL 数据库中。

程序启动很快,每秒可以处理 30 或 40 行,但随着时间的推移逐渐变慢,我不知道为什么。我相信我正在以良好的速度处理物品。

我在 vfpoledb 中使用的连接字符串是

"Provider=vfpoledb;Data Source=" + sourceDBFolder + ";Collating Sequence=machine;MVCOUNT=32000;ENGINEBEHAVIOR=90;TABLEVALIDATE=0;REFRESH=0";

其中 sourceDBFolder 是磁盘上的路径。在开始任务之前,我还执行了以下代码:

System.Data.OleDb.OleDbCommand oRefreshCommand = oConn.CreateCommand();
oRefreshCommand.CommandText = "EXECSCRIPT([SET REFRESH TO 0,0])";
oRefreshCommand.ExecuteNonQuery();

这是相关的代码。select 语句中的 where 子句如果不按下面的顺序排列,就会造成瓶颈。

string[] noteTables = new string[] { "note1", "note2", "note3", "note4", "note5", "note6" };
foreach (long lNoteKey in oCaseLookupTable.Keys) {
  for (int y = 0; y <= 5; y++) {
    System.Data.OleDb.OleDbCommand oNotesCmd = oConn.CreateCommand();
    oNotesCmd.CommandText = "SELECT NOTEDATE, NOTEDESC, ENTEREDBY FROM " + noteTables[y] + " WHERE NOTEPOINT = " + lNoteKey.ToString() + " AND NOTEDESC NOT LIKE 'Folder accessed%'";
    DataTable oNotesTable = new DataTable();
    oNotesTable.Load(oNotesCmd.ExecuteReader());
    foreach (DataRow oRow in oNotesTable.Rows) { 
      //Do processing on rows, Note is my created class.
      Note oNote = new Note();
      oNote.NoteValue = oRow["NOTEDESC"].ToString().Trim();
      oNote.ReferenceID = oCaseLookupTable[lNoteKey];
      DateTime createdDate;
      if (DateTime.TryParse(oRow["NOTEDATE"].ToString().Trim(), out createdDate))
        oNote.CreatedDate = createdDate;
      else
        oNote.CreatedDate = DateTime.Now;
      Result oNoteResult = oNote.Insert();
    }
    oNotesTable.Dispose();
    oNotesCmd.Dispose();
  }
}

简而言之,我不明白为什么这会变得越来越慢。PerfMon 没有显示任何随时间增长的托管内存块。我尝试通过连续调用 DBF 文件来保持我的 DataTable 很小。通常,查询将返回的最大行数为 1,000。

4

3 回答 3

1

您正在执行 Rushmore 的查询是否经过优化,即表上是否有字段 NOTEPOINT 和 NOTEDESC 的索引?

于 2012-07-20T08:38:46.473 回答
0

将代码转换为使用DataReader代替DataTable. 使用while循环迭代结果。我相信上的foreach循环DataTable也在减慢速度。由于您只向前读取值,这将为您带来性能改进:

有关更多信息,请参阅性能比较:数据访问技术,尤其是部分DataReader vs. DataSet

对于需要优化的只读和只进数据访问的应用程序,DataReader 是更好的选择。越早从 DataReader 加载数据、关闭 DataReader 并关闭数据库连接,获得的性能就越好。由于 DataReader 持有的数据库连接在应用程序读取数据时不能用于任何其他目的,因此如果应用程序持有 DataReader 的时间足够长以至于发生争用,它可能会限制可伸缩性。DataSet 只需要在填充时保持连接。一旦它被填满,连接可能会被关闭并返回到池中。延迟从 DataSet 读取数据不会导致发生争用,因为连接可能已经返回到池中。

于 2012-07-20T14:40:51.503 回答
0

问题是 SQL 端表上的一些数据库触发器。在操作期间禁用它们(在这种情况下不需要它们)解决了这个问题。

于 2012-07-25T22:13:58.727 回答