我正在使用MySqlDataAdapter将MySQL中的表转储到DataTable对象中。数据库输入和输出正常,但我的应用程序代码似乎有一个性能问题,我能够追踪到特定的LINQ语句。
目标很简单,在DataTable的内容中搜索与特定字符串匹配的列值,就像传统的WHERE column = 'text'
SQL子句一样。
简化代码:
foreach (String someValue in someList) {
String searchCode = OutOfScopeFunction(someValue);
var results = emoteTable.AsEnumerable()
.Where(myRow => myRow.Field<String>("code") == searchCode)
.Take(1);
if (results.Any()) {
results.First()["columnname"] = 10;
}
}
此简化代码执行数千次,someList
中的每个条目执行一次。当我运行Visual Studio Performance Profiler时,我发现“results.Any()
”行突出显示占用了93.5%的执行时间。
我已经尝试了几种不同的方法来优化此代码,但没有一种方法在保持emoteTable
DataTable作为数据主要来源的同时提高了性能。我可以在foreach之外将emoteTable
转换为Dictionary<String, DataRow>
,但之后我必须保持DataTable和Dictionary同步,这仍然是性能改进,但感觉不对。
三个问题:
results.Any()
行消耗90%以上的资源?在这种情况下,更有意义的是var results
行应该消耗资源,毕竟,它是执行实际搜索的行,对吗?感谢您的时间。如果我找到答案,我也会在这里发布。
答案 0 :(得分:0)
Any()
占用了90%的时间,因为result
是only executed when you call Any()
。在致电Any()
之前,实际上并未进行查询。
看起来问题是你首先将整个表格取入内存然后进行搜索。您应该指示您的数据库进行搜索
此外,当您致电results.First()
时,将再次执行整个results
查询。
考虑到延迟执行,您应该编写类似
的内容var result = emoteTable.AsEnumerable()
.Where(myRow => myRow.Field<String>("code") == searchCode)
.FirstOrDefault();
if (result != null) {
result["columnname"] = 10;
}
答案 1 :(得分:0)
您实施的内容几乎是加入:
var searchCodes = someList.Select(OutOfScopeFunction);
var emotes = emoteTable.AsEnumerable();
var results = Enumerable.Join(emotes, searchCodes, e=>e, sc=>sc.Field<String>("code"), (e, sc)=>sc);
foreach(var result in results)
{
result["columnname"] = 10;
}
Join可能会使用某种查找来优化对两个列表的访问。
但我要做的第一件事就是彻底放弃组合DataTable和LINQ的想法。它们是两种不同的技术,并试图断言它们在合并时可能会做什么很难。
您是否尝试过进行原始UPDATE调用?您希望更新多少项?