如何提高此功能的效率。它目前运行在6 - 45秒。 我已经在这个特定方法上运行了dotTrace探查器,它的总时间在6,000到45,000毫秒之间。大部分时间花在“MoveNext”和“GetEnumerator”调用上。
和时间的例子是
71.55% CreateTableFromReportDataColumns - 18, 533* ms - 190 calls
-- 55.71% MoveNext - 14,422ms - 10,775 calls
我可以加快这种方法吗?它会被调用很多,秒数加起来:
private static DataTable CreateTableFromReportDataColumns(Report report)
{
DataTable table = new DataTable();
HashSet<String> colsToAdd = new HashSet<String> { "DataStream" };
foreach (ReportData reportData in report.ReportDatas)
{
IEnumerable<string> cols = reportData.ReportDataColumns.Where(c => !String.IsNullOrEmpty(c.Name)).Select(x => x.Name).Distinct();
foreach (var s in cols)
{
if (!String.IsNullOrEmpty(s))
colsToAdd.Add(s);
}
}
foreach (string col in colsToAdd)
{
table.Columns.Add(col);
}
return table;
}
如果你需要sql表定义,它们是:
ReportData
ReportID int
ReportDataColumn
ReportDataColumnId int
ReportDataId int
Name varchar(255)
Value text
答案 0 :(得分:4)
我相信你应该能够将你的功能简化为类似的东西
var columnsToAdd = report.ReportDatas
.SelectMany(r => r.ReportDataColumns)
.Select(rdc => rdc.Name)
.Distinct()
.Where(name => !string.IsNullOrEmpty(name));
然后从那里添加名字。
答案 1 :(得分:3)
您的代码(仅)运行foreach循环,因此该方法在MoveNext()等中花费大部分时间的结论并不令人惊讶。
您正在对isnullOrEmpty和Distinct进行双重处理(由HashSet重复)。
我的版本是:
private static DataTable CreateTableFromReportDataColumns(Report report)
{
DataTable table = new DataTable();
HashSet<String> colsToAdd = new HashSet<String> { "DataStream" };
foreach (ReportData reportData in report.ReportDatas)
{
foreach (var column in reportData.ReportDataColumns)
{
if (!String.IsNullOrEmpty(column.Name))
colsToAdd.Add(column.Name);
}
}
foreach (string col in colsToAdd)
{
table.Columns.Add(col);
}
return table;
}
但我不希望有大的进步
答案 2 :(得分:1)
当你提出问题时,你应该提到LinqToSql,然后你会得到一些回复来查看你的数据库,看看它是一个长时间运行的查询还是重复往返查询
private static DataTable CreateTableFromReportDataColumns(Report report)
{
DataTable table = new DataTable();
table.Columns.Add("DataStream");
IEnumerable<string> moreColumns = report.ReportDatas
.SelectMany(z => z.ReportDataColumns)
.Select(x => x.Name)
.Where(s => s != null && s != "")
.Distinct();
foreach (string col in moreColumns)
{
table.Columns.Add(col);
}
return table;
}
此外,捕获使用sql profiler发出的查询。然后通过在
之前运行这些语句来分析查询的IO和TIMESET STATISTICS TIME ON
SET STATISTICS IO ON
--your query here
最后,您可能需要一两个索引来降低IO。列顺序在这里很重要。
CREATE INDEX IX1_ReportData ON ReportData(ReportID, Id)
CREATE INDEX IX1_ReportDataColumn ON ReportDataColumn(ReportDataId, Name)
答案 3 :(得分:0)
这可能有点过头了(取决于ReportDatas中的条目数,每个ReportDataColumns中的列数,主机上的核心数等),但您也可以进行并行化。
例如,如果您决定并行处理ReportDatas条目,则可以让每个条目创建自己的列集合,或者让它们全部写入ConcurrentBag,当它完成时或者其他任何内容时,您将不同。
答案 4 :(得分:0)
这可能会对Hank的代码略有改进。它利用了HashSet将告诉您Add操作是否成功或元素是否已存在的事实。
private static DataTable CreateTableFromReportDataColumns(Report report)
{
HashSet<string> uniqueNames = new HashSet<string> { null, "", "DataStream" };
DataTable table = new DataTable();
table.Columns.Add("DataStream");
foreach (ReportData reportData in report.ReportDatas)
{
foreach (var dataColumn in reportData.ReportDataColumns)
{
if (uniqueNames.Add(dataColumn.Name))
{
table.Columns.Add(dataColumn.Name);
}
}
}
return table;
}
编辑:我继续将null和“”添加到开头的哈希集中,因此我们不再需要检查null或为空。