我有一个.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。
答案 0 :(得分:1)
您正在执行Rushmore的查询是否已经优化,即表中是否存在NOTEPOINT和NOTEDESC字段的索引?
答案 1 :(得分:0)
转换代码以使用DataReader
而不是DataTable
。使用while
循环迭代结果。我相信foreach
上的DataTable
循环也会减慢速度。由于您只是向前阅读值,这将为您带来性能提升:
有关详情,请参阅Performance Comparison: Data Access Techniques,尤其是DataReader vs. DataSet
对于需要的应用程序,DataReader是更好的选择 优化的只读和仅向前数据访问。你越早装载 关闭DataReader的数据,关闭DataReader,然后关闭 数据库连接,您获得的性能会更好。因为 DataReader拥有一个不能用于任何数据库的数据库连接 应用程序读取数据时的其他目的,可能会限制 如果应用程序持有DataReader足够长的可扩展性 争用发生。 DataSet只需要保持连接 它正在填充。填充后,可以关闭连接 并返回游泳池。延迟从DataSet读取数据 不会引起争用,因为连接可能已经发生 已经回到了游泳池。
答案 2 :(得分:0)
问题是SQL端的表上有一些数据库触发器。在操作期间禁用它们(在这种情况下不需要它们)解决了这个问题。