目前,我正在为一个早已离开的人(我的意思是离开公司)编写的旧项目代码进行性能改进。 我想改进的代码是:
DataTable dtSource = new DataTable();
DataTable dtSourceTemp = new DataTable();
dtSource = GetData();
dtSourceTemp = dtSource.Copy();
foreach (DataRow item in dtSource.Rows)
{
if (Functions.parseString(item["COL_1"]).Equals("NG"))
{
foreach (DataRow itemTemp in dtSourceTemp.Rows)
{
if (Functions.parseString(itemTemp["PK_1"]).Equals(Functions.parseString(item["PK_1"]))
&& Functions.parseString(itemTemp["PK_2"]).Equals(Functions.parseString(item["PK_2"]))
&& Functions.parseString(itemTemp["PK_3"]).Equals(Functions.parseString(item["PK_3"])))
{
itemTemp["COL_1"] = "NG";
}
}
}
}
逻辑是数据有4个主键(PK_1,PK_2,PK_3,PK_4)。 PK_1到3将定义项目系列,PK_4将是系列中的项目数。
如果系列中的任何项目是NG,则系列中的所有项目都是NG。
对于上面的代码,每次运行此代码时大约有80K条记录,将有更新的6.400.000.000循环(如果每个系列至少有1个NG项目)80.000行,这是非常低效的。
任何人都可以给我一个如何改进的建议吗?
请注意,所有这些工作都是为了向屏幕显示所需的数据(dtSourceTemp将是数据源),而不是实际更新数据库中的数据。
更新:
在思考之后,我认为这会更好:
DataTable dtSource = new DataTable();
DataRow[] drSource = dtSource.Select("COL_1 = 'NG'");
foreach(DataRow dr in drSource)
{
string pk1 = dr["PK_1"].toString();
string pk2 = dr["PK_2"].toString();
string pk3 = dr["PK_3"].toString();
//TO-DO:Code to update data in dtSource based on 3 PK
//Something equal to SQL Script "Update tbl set COL_1 = 'NG' WHERE ...."
}
但是,我目前仍然在更新dtSource的数据,因为C#似乎没有任何可以做我想要的DataTable的功能。
答案 0 :(得分:0)
由于您使用的是基本循环并且无法将其移动到数据库,因此优化程度不高。
话虽如此,你可以尝试调整某些事情,我会借此机会抛弃这可能会在https://codereview.stackexchange.com/中提出
1 - Functions.parseString
实际上会导致瓶颈的第一件事是Functions.parseString()
正在做的事情。这应该是首先考虑并开始编写单元测试以确定基线并测量10,000次分析的速度与您认为会使其更快的任何变化。
2 - 更改If
条件的顺序
根据实际存储的数据,您可以通过更改顺序来创建速度增加,以便更快地进行短路。
如果您的PK_#
列类似于A,B,1 | A,B,2 | A,B,3
等,那么最好先更改订单,以便在其他项目之前先检查PK_3
,这样它就不会出现问题。在PK_3不匹配的情况下,大多数时间拨打parseString
4次。基本上,首先尝试按最独特的价值订购。
3 - 缓存某些值
为什么在每个项目总是相同时解析一些东西?
foreach (DataRow item in dtSource.Rows)
{
if (Functions.parseString(item["COL_1"]).Equals("NG"))
{
var pk1 = Functions.parseString(item["PK_1"])
var pk2 = Functions.parseString(item["PK_2"])
var pk3 = Functions.parseString(item["PK_3"])
foreach (DataRow itemTemp in dtSourceTemp.Rows)
{
if (Functions.parseString(itemTemp["PK_1"]).Equals(pk1)
&& Functions.parseString(itemTemp["PK_2"]).Equals(pk2)
&& Functions.parseString(itemTemp["PK_3"]).Equals(pk3))
{
itemTemp["COL_1"] = "NG";
}
}
}
}
4 - 运行SQL查询而不是代码
(未经测试的MSSQL示例)
UPDATE YT
SET YT.COL_1 = 'NG'
FROM YOUR_TABLE YT
WHERE EXISTS (
SELECT 1
FROM YOUR_TABLE YT2
WHERE YT2.COL_1 = 'NG'
AND YT.PK_1 = YT2.PK_1
AND YT.PK_2 = YT2.PK_2
AND YT.PK_3 = YT2.PK_3
)
你真的没有其他的事情可做。你拥有的是超级基本的,并且大部分完全依赖于运行过程的处理器。