关于优化for循环的注意的事项
for循环注意事项:
1.for循环内部尽量少做数据库查询之类的IO代价大的操作
2.尽量控制for循环的次数,不多做无用功
3.能一次加载在内存中的,就不要通过循环来多次查询数据库,除非数据量过大。
4.for循环内部尽可能少创建对象,会耗费大量内存资源
起因:
前两天优化一个统计功能的页面,客户反映说,点击页面的查询按钮要等快十秒中数据才加载出来,然后点击导出按钮后,加载时间快翻一倍了。让我查一下看看能不能优化。
仔细看了一下代码,才发现代码问题太大了。
发现问题:
描述一下优化前大致结构:
1.从相关主表中获取所有工单信息,存储到dataset,然后通过for循环读取数据到一个工单对象的list中。
2.获取用来修理工单所用的材料信息,放在一个dataset中,然后外循环dataset,内循环工单对象list。根据关联ID值相等来判断,把相关材料信息赋值给工单对象的材料信息属性。
3.for循环工单对象的list来生成拼接统计html,循环中放了一个查询sql,生成一个dataset,用dataset中第一行第一列的值来和工单对象的一个属性来做比较,然后生成不同内容
4.在for循环结束处放了一个判断,如果小于200行,那就继续添加拼接的html。
把不相关代码删除后,附上代码结构
/// <summary>
/// 查询所有符合条件的工单对象
/// </summary>
/// <returns></returns>
protected ArrayList SearchRecord()
{
OracleDataBase odb = new OracleDataBase();//封装的oracle操作类
ArrayList xlgctjArr = new ArrayList();
string sql = "select t.id xltjid,t.accepttime,tz.EXECUTIVEPEOPLE,EXECUTIVECONTENT,occurreason,resolvent, EXECUTIVEREMARK,'' as SGD,t1.kgsj,tz.EXECUTIVETIME,t.*,t1.lsxz,t1.cz,t1.lssb,t1.lmxz,t1.KJ, t.source as ISZKD,tz.executiveintime as ISINTIME from TZ_MAIN t , v_tz_xiaowxiuanddaxiu_wxzt t1, tz_main_clinfo tz where t.id=tz.main_id and tz.EXECUTIVEPEOPLE is not null and ACCEPTSTATION in (" + Session["DEPNAME"].ToString() + ") and t.id=t1.mainid(+) and (t1.FIXTYPE='0' or t1.FIXTYPE is null)";
//相关过滤判断条件已删除
sql += " order by t.accepttime asc ";
if (sql != "")
{
DataSet ds = new DataSet();
try
{
ds = odb.GetDataSet(sql);
if (ds != null && ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
{
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
DataRow dbrd = ds.Tables[0].Rows[i];
xlgctjBean xltj = new xlgctjBean();
xltj.xltjId = dbrd["xltjid"].ToString();
xltj.REPORTTYPE = dbrd["REPORTTYPE"].ToString();//反映类别
xltj.REPORTCONTENT = dbrd["REPORTCONTENT"].ToString();//反映内容
xlgctjArr.Add(xltj);
}
}
} catch (Exception ex)
{
Loger.Debug("tjbb_xlmx.SearchRecord()==>" + sql, ex);
}
finally
{
if (ds != null)
ds.Dispose(); }
sql = "select t1.id,t2.xlhycl from tz_main t1,v_tz_xiaowxiuanddaxiu_cailiao t2, tz_main_clinfo tz where t1.id=tz.Main_id(+) and t1.id=t2.mainid and t1.reporttype in ('套室表','水管设备','水管问题') and tz.EXECUTIVEPEOPLE!=' ' and tz.EXECUTIVEPEOPLE is not null and ACCEPTSTATION in (" + Session["DEPNAME"].ToString() + ") ";
//相关过滤判断条件已删除 sql += " order by t1.accepttime asc ";
ds = odb.GetDataSet(sql);
if (ds != null && ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
{
for (int j = 0; j < ds.Tables[0].Rows.Count; j++)
{
for (int i = 0; i < xlgctjArr.Count; i++)
{
if (((xlgctjBean)xlgctjArr[i]).xltjId == ds.Tables[0].Rows[j]["id"].ToString())
{
if (((xlgctjBean)xlgctjArr[i]).XLHYCL != null && ((xlgctjBean)xlgctjArr[i]).XLHYCL != "")
{ ((xlgctjBean)xlgctjArr[i]).XLHYCL = ((xlgctjBean)xlgctjArr[i]).XLHYCL + ";" + ds.Tables[0].Rows[j]["xlhycl"].ToString();//
}
else
{
((xlgctjBean)xlgctjArr[i]).XLHYCL = ds.Tables[0].Rows[j]["xlhycl"].ToString();
}
}
} }
}
}
return xlgctjArr;
} /// <summary>
/// 通过xlgctjArr 拼接html
/// </summary>
/// <param name="isAll">0,表示查询,只用显示200条数据即可,1表示导出功能,导出所有数据</param>
/// <param name="xlgctjArr">工单对象列表</param>
/// <returns></returns>
protected string ShowTable(string isAll, ArrayList xlgctjArr)
{
string html = "";
string htmlstr = "";
htmlExportstr = "";
//增加工时系数统计
for (int i = 0; i < xlgctjArr.Count; i++, s++)
{
html = "";
string jbsj = string.Empty;
string xfsj = string.Empty;
string kgsj = string.Empty;
xlgctjBean tempxlgctjBean = (xlgctjBean)xlgctjArr[i];
if (i % 2 == 0)
{ }
else
html += "<tr>";
html += "<td>" + (s + 1) + "</td>";
if (((xlgctjBean)xlgctjArr[i]).REPORTTYPE != null && ((xlgctjBean)xlgctjArr[i]).REPORTTYPE != "")
{
html += "<td>" + ((xlgctjBean)xlgctjArr[i]).REPORTTYPE + "</td>";
}
else
{
html += "<td> </td>";
}
//统计类型
OracleDataBase odb1 = new OracleDataBase();
string sql = string.Format(@"select * from STATISTICALTYEP");
DataSet dtStatisticalType = odb1.GetDataSet(sql); if (dtStatisticalType != null && dtStatisticalType.Tables.Count > 0)
{
if (dtStatisticalType.Tables[0].Rows[0]["TYPE"].ToString() == "接报时间")
{
html += "<td>" + publicbean.resultValue(jbsj) + "</td>";
}
else if (dtStatisticalType.Tables[0].Rows[0]["TYPE"].ToString() == "开工日期")
{
html += "<td>" + publicbean.resultValue(kgsj) + "</td>";
}
else if (dtStatisticalType.Tables[0].Rows[0]["TYPE"].ToString() == "修复日期")
{
html += "<td>" + publicbean.resultValue(xfsj) + "</td>";
} }
else
{
html += "<td>0</td>";
}
html += "</tr>";
if (isAll == "")
{
if (i < 200)
{
htmlstr += html;
}
}
htmlstr += html;
htmlExportstr += html;//用于导出保存
} htmlstr += "</table>";
htmlExportstr += "</table>";
return htmlstr;
}
优化后:
由于时间紧,差不多修改优化了一下,等有时间的时候把业务了解清楚,准备再次进行优化。贴上优化后部分代码
/// <summary>
/// 查询所有符合条件的工单对象
/// </summary>
/// <returns></returns>
protected ArrayList SearchRecord()
{
OracleDataBase odb = new OracleDataBase();
string sql = " select t.id xltjid,t.accepttime,EXECUTIVECONTENT,occurreason,resolvent, EXECUTIVEREMARK,'' as SGD,tz.EXECUTIVETIME,t.*,t1.kgsj,t1.lsxz,t1.cz,t1.lssb,t1.lmxz , t.source as ISZKD,tz.executiveintime as ISINTIME from TZ_MAIN t ,v_tz_xiaowxiuanddaxiu_wxzt t1,tz_main_clinfo tz where t.id=tz.main_id and t.reporttype in ('套室表','水管设备','水管问题') and tz.EXECUTIVEPEOPLE is not null and ACCEPTSTATION in (" + Session["DEPNAME"].ToString() + ") and t.id=t1.mainid(+) and ( t1.FIXTYPE='1' or t1.FIXTYPE is null)";
//相关过滤判断条件已删除 sql += " order by t.accepttime asc "; ArrayList xlgctjArr = new ArrayList();
if (sql != "")
{
ArrayList xltjIds = new ArrayList();
DataSet ds = new DataSet();
try
{
ds = odb.GetDataSet(sql);
if (ds != null && ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
{
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
DataRow dbrd = ds.Tables[0].Rows[i];
xlgctjBean xltj = new xlgctjBean();
xltj.xltjId = dbrd["xltjid"].ToString();
xltj.REPORTTYPE = dbrd["REPORTTYPE"].ToString();//反映类别
xltj.REPORTCONTENT = dbrd["REPORTCONTENT"].ToString();//反映内容
xlgctjArr.Add(xltj);
}
}
}
catch (Exception ex)
{
Loger.Debug("tjbb_gwsbyhmx.SearchRecord()1==>" + sql, ex);
}
finally
{
if (ds != null)
ds.Dispose();
}
sql = "select t1.id,t2.xlhycl from tz_main t1,v_tz_xiaowxiuanddaxiu_cailiao t2 ,tz_main_clinfo tz where t1.id=tz.Main_id(+) and t1.id=t2.mainid and t1.reporttype in ('套室表','水管设备','水管问题') and tz.EXECUTIVEPEOPLE is not null and ACCEPTSTATION in (" + Session["DEPNAME"].ToString() + ") "; sql += " order by t1.accepttime asc ";
ds = odb.GetDataSet(sql);
if (ds != null && ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
{
for (int j = 0; j < ds.Tables[0].Rows.Count; j++)
{
for (int i = 0; i < xlgctjArr.Count; i++)
{
if (((xlgctjBean)xlgctjArr[i]).xltjId == ds.Tables[0].Rows[j]["id"].ToString())
{
if (((xlgctjBean)xlgctjArr[i]).XLHYCL != null && ((xlgctjBean)xlgctjArr[i]).XLHYCL != "")
{ ((xlgctjBean)xlgctjArr[i]).XLHYCL = ((xlgctjBean)xlgctjArr[i]).XLHYCL + ";" + ds.Tables[0].Rows[j]["xlhycl"].ToString();//修理耗用材料--TZ_DAXIUCLD
}
else
{
((xlgctjBean)xlgctjArr[i]).XLHYCL = ds.Tables[0].Rows[j]["xlhycl"].ToString();
}
}
}
} } }
Session.Add("xlgctjArr", xlgctjArr);
return xlgctjArr; }
/// <summary>
/// 通过xlgctjArr 拼接html
/// </summary>
/// <param name="isAll">0,表示查询,只用显示200条数据即可,1表示导出功能,导出所有数据</param>
/// <param name="xlgctjArr">工单对象列表</param>
/// <returns></returns>
protected string ShowTable(string isAll, ArrayList xlgctjArr)
{
string html = "";
string htmlstr = "";
htmlExportstr = ""; ReocrdCount = xlgctjArr.Count.ToString();
int Allcount = 200;
OracleDataBase odb1 = new OracleDataBase();
string sql = string.Format(@"select * from STATISTICALTYEP");
DataTable dtStatisticalType = odb1.GetDataSet(sql).Tables[0];
string dtStatisticalTypeResult = dtStatisticalType.Rows[0]["TYPE"].ToString();
int s = 0;
if (isAll == "")
{
Allcount = xlgctjArr.Count > 200 ? 200 : xlgctjArr.Count;
}
else
{
Allcount = xlgctjArr.Count;
if (isAll == "1")
{
s = 200;
}
} for (int i = 0; i < Allcount; i++, s++)
{
html = "";
string jbsj = string.Empty;
string xfsj = string.Empty;
string kgsj = string.Empty; if (i % 2 != 0)
{
html += "<tr>";
} html += "<td>" + (s + 1) + "</td>";
if (((xlgctjBean)xlgctjArr[i]).REPORTTYPE != null && ((xlgctjBean)xlgctjArr[i]).REPORTTYPE != "")
{
html += "<td>" + ((xlgctjBean)xlgctjArr[i]).REPORTTYPE + "</td>";
}
else
{
html += "<td> </td>";
} //统计类型 if (dtStatisticalType.Rows.Count > 0)
{ if (dtStatisticalTypeResult == "接报时间")
{
html += "<td>" + publicbean.resultValue(jbsj) + "</td>";
}
else if (dtStatisticalTypeResult == "开工日期")
{
html += "<td>" + publicbean.resultValue(kgsj) + "</td>";
}
else if (dtStatisticalTypeResult == "修复日期")
{
html += "<td>" + publicbean.resultValue(xfsj) + "</td>";
}
}
else
{
html += "<td>0</td>";
}
html += "</tr>";
//if (isAll == "")
//{
// if (i < 200)
// {
// htmlstr += html;
// }
//}
htmlstr += html;
htmlExportstr += html;//用于导出保存
} htmlstr += "</table>";
htmlExportstr += "</table>";
//}
return htmlstr;
}
本次主要优化地方:
1.for循环工单对象的list来生成拼接统计html,循环中放了一个查询sql,生成一个dataset,用dataset中第一行第一列的值来和工单对象的一个属性来做比较,然后生成不同内容.=======>数据库IO代价太大,在for循环内做数据库读取操作的话,最好能放在For循环外面,多花一点内存比每次读取数据库的开销小很多
2.在for循环结束处放了一个判断,如果小于200行,那就继续添加拼接的html。=====》直接判断好数量,尽量少做循环。
3.关于导出的优化,由于业务规则是先查询然后导出。所以我把查询时封装的工单对象列表和生成的html字符串都保存在session中,等导出的时候。判断工单对象列表count小于等于200的话,直接把session中的html导出就好。如果大于200,把超过200的list调用生成html的方法ShowTable()直接生成剩下的html,然后和session中的html拼接后导出即可
注:下周有时间的话,去了解一下关于这个统计的业务,如果可能的话,把生成工单对象列表的三个for循环优化的只剩一个,这样性能才能翻翻!
关于优化for循环的注意的事项的更多相关文章
- 【ABAP系列】SAP ABAP 优化LOOP循环的一点点建议
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP 优化LOOP循 ...
- python列表与集合,以及循环时的注意事项
一.python列表 序列是Python中最基本的数据结构.序列中的每个元素都分配一个数字 - 它的位置,或索引,第一个索引是0,第二个索引是1,往后数的最后一个为-1依此类推. Python有6个序 ...
- 使用HashMap或Hashset优化使用循环判断字符串中是否含有重复元素
原本遇到判断字符串中是否含有重复元素的问题总是使用for循环遍历进行判断,这一方法则需要O(n3)的时间复杂度,如果本身方法处于几个循环中,就会指数倍增加时间复杂度.类似于如下代码: String[] ...
- BigDecimal 在for循环中相加注意事项
public static void main(String[] args) { BigDecimal bigDecimal = new BigDecimal(1); for (int i = 0; ...
- 使用forin循环时的注意事项
由于遍历的对象为nil,从而导致的现象是里面的循环体根本就没有执行,并且编译器和运行期都不会报错.因为,OC语法是运行向nil发送消息的. for (WSFActivitySelectSpaceCel ...
- Objective-C 高性能的循环遍历 forin - NSEnumerator - 枚举 优化
Cocoa编程的一个通常的任务是要去循环遍历一个对象的集合 (例如,一个 NSArray, NSSet 或者是 NSDictionary). 这个看似简单的问题有广泛数量的解决方案,它们中的许多不乏 ...
- MySQL的JOIN(三):JOIN优化实践之内循环的次数
这篇博文讲述如何优化内循环的次数.内循环的次数受驱动表的记录数所影响,驱动表记录数越多,内循环就越多,连接效率就越低下,所以尽量用小表驱动大表.先插入测试数据. CREATE TABLE t1 ( i ...
- TI C6000 优化进阶:循环最重要!
软件流水循环 1. C6000流水线(Pipeline) 一个指令的处理过程并不是一步完成,它被分为三个阶段:取指(Fetch).译码(Decode).执行(Excute).将每一个阶段放入独立的流程 ...
- java关于for循环的效率优化
我们知道在实现一个功能的时候是可以使用不同的代码来实现的,那么相应的不同实现方法的性能肯定也是有差别的,所以我们在写一些对性能很敏感的模块的时候,对代码进行优化是很必要的,所以我们说一下for循环(w ...
随机推荐
- 关于table排版
colspan和rowspan这两个属性用于创建特殊的表格. colspan是“column span(跨列)”的缩写.colspan属性用在td标签中,用来指定单元格横向跨越的列数: 在浏览器中 ...
- php多线程操作数据库(转)
PHP用pcntl可以实现多线程操作数据库.直接上代码,逻辑自己研究喽. 示例代码为: /** * 并发多线程运行任务,把任务拆解成区块,用多线程去并发执行 * @param callable $ex ...
- ES : 软件工程学的复杂度理论及物理学解释
系统论里面总是有一些通用的专业术语 比如复杂度.熵.焓,复杂度专门独立出来,成为复杂度理论 文章摘抄于:<非线性动力学> 刘秉政 编著 5.5 复杂性及其测度 热力学的几个专业术语 熵. ...
- MongoDB 学习笔记(三):分页、排序与游标
一.分页 1.limit返回指定条数的数据 2.skip指定跨度 3.limit与skip结合,进行分页 二.排序 1.sort排序:指定排序的key,大于0为升序,小于0为降序.如果指定了多个排序键 ...
- php libevent扩展
Libevent 是一个用C语言编写的.轻量级的开源高性能网络库,主要有以下几个亮点:事件驱动( event-driven),高性能;轻量级,专注于网络,不如 ACE 那么臃肿庞大: 源代码相当精炼. ...
- bzoj 1293: [SCOI2009]生日礼物 问题转化 + 性质分析 + 滚动数组优化
Description 小西有一条很长的彩带,彩带上挂着各式各样的彩珠.已知彩珠有N个,分为K种.简单的说,可以将彩带考虑为x轴,每一个彩珠有一个对应的坐标(即位置).某些坐标上可以没有彩珠,但多个彩 ...
- 研究发现:TLS1.3中的 TLS 对话恢复机制可以追踪用户
由于隐私浏览器技术的日渐成熟,网站越来越无法通过 Cookie 和网页浏览器特征来追踪用户,但道高一尺魔高一丈,现在这些网站会用 TLS 1.3 中的 TLS 对话恢复机制追踪用户. 你以为禁用浏览器 ...
- 如何在sublime上运行php
这个问题虽然随便一搜都能有很多答案,但是我当时都没有顺利解决我会详细地写出较为容易理解和操作的步骤第一步,配置PHP环境变量如图一所示1.找到 我的电脑 -属性2.高级系统设置3.环境变量4.找到“系 ...
- python面向对象三大特性之一封装
一.什么是封装 在程序设计中,封装(Encapsulation)是对具体对象的一种抽象,即将某些部分隐藏起来,在程序外部看不到,其 含义是其他程序无法调用. 要了解封装,离不开“私有化”,就是将类或者 ...
- 基于Tags的简单内容推荐的实现
原来为了简单方便,自己小网站上的文章页的相关内容推荐就是从数据库里随机抽取数据来填充一个列表,所以一点相关性都没有,更本没有办法引导用户去访问推荐内容. 算法选择 如何能做到相似内容的推荐呢,碍于小网 ...