关于优化for循环的注意的事项

for循环注意事项:

1.for循环内部尽量少做数据库查询之类的IO代价大的操作

2.尽量控制for循环的次数,不多做无用功

3.能一次加载在内存中的,就不要通过循环来多次查询数据库,除非数据量过大。

起因:

前两天优化一个统计功能的页面,客户反映说,点击页面的查询按钮要等快十秒中数据才加载出来,然后点击导出按钮后,加载时间快翻一倍了。让我查一下看看能不能优化。

仔细看了一下代码,才发现代码问题太大了。

发现问题:

描述一下优化前大致结构:

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循环优化的只剩一个,这样性能才能翻翻!

时间: 2024-10-25 21:28:13

关于优化for循环的注意的事项的相关文章

Linux for循环执行命令注意事项

如果for循环命令中带有一些符号,需要用()括起来. for i in {1..4}; do (python /data/UGCRobot/manage/Scheduler.py 1.log > /dev/null 2>&1 &); done Linux for循环执行命令注意事项

javascript性能优化之循环迭代(duff)

这段时间一直再学习<高性能javascript>这本书,在这里记录一些学习心得和笔记... 循环迭代之“Duff's Device”优化迭代次数在1000以上的循环. 函数如下: 1 function duff(items) { 2 if(items && items.length) { 3 var l = items.length, i = l % 8; 4 while(i) { 5 console.log(items[-- l]); 6 i --; 7 } 8 i = Ma

shell中使用while循环ssh的注意事项

需要读取一个文本,次文本每一行包含一个IP在while循环中使用ssh,但ssh完第一行后就退出了,如何避免自动读取一行就跳出while循环,此文将详细解释其原因.      最近在写一个自动更新的shell,可是发现如果在使用while循环从一个文件中读取ip地址,然后访问就只能读取第一行纪录.代码如下: while read LINE do echo *******************************************$LINE ssh 192.168.10.233 ls

iOS 循环利用的注意事项

1.UI控件自带的循环利用 UITableView,UICollectionView,本身自带循环利用,通过标识符在缓存池中找cell 需要注意的地方:给cell传模型数据的时,要做到全覆盖,如果只是cell.Text1 = dataText1,那么新显示的cell的Image和Text2将会显示旧数据 2.在UIScrollView上做循环利用 思路: a.取得待展示的数据个数count1,取得当前已初始化的控件个数count2 (假设是UIView,并且需要有1个数组装着UIView,该数组

python循环修改列表注意事项

python循环列表且需要修改列表元素时,需注意不能边循环列表,边修改列表,否则会导致莫名奇妙的结果错误. 以简单的冒泡排序的一次排序为例 将列表[12, 3, 15, 7, 45, 33, 9, 76, 40, 56]使用冒泡算法按照从小到大排序.(仅写一次排序过程,即找到最大的放到最后) 如果写为: src_list = [12, 3, 15, 7, 45, 33, 9, 76, 40, 56] for (index, value) in enumerate(src_list[:-1]): 

Objective-C 高性能的循环遍历 forin - NSEnumerator - 枚举 优化

Cocoa编程的一个通常的任务是要去循环遍历一个对象的集合  (例如,一个 NSArray, NSSet 或者是 NSDictionary). 这个看似简单的问题有广泛数量的解决方案,它们中的许多不乏有对性能方面问题的细微考虑. 对于速度的追求 首先,是一个免责声明: 相比其它问题而言,一个 Objective-C 方法原始的速度是你在编程时最后才需要考虑的问题之一 – 区别就在于这个问题够不上去同其它更加需要重点考虑的问题进行比较,比如说代码的清晰度和可读性. 但速度的次要性并不妨碍我们去理解

MySQL的JOIN(三):JOIN优化实践之内循环的次数

这篇博文讲述如何优化内循环的次数.内循环的次数受驱动表的记录数所影响,驱动表记录数越多,内循环就越多,连接效率就越低下,所以尽量用小表驱动大表.先插入测试数据. CREATE TABLE t1 ( id INT PRIMARY KEY AUTO_INCREMENT, type INT ); SELECT COUNT(*) FROM t1; +----------+ | COUNT(*) | +----------+ | 10000 | +----------+ CREATE TABLE t2 (

sql优化(oracle)- 第三部分 &#160;sql优化总结

第三部分  sql优化总结        1. 优化一般原则        2. 具体注意事项 1. SQL优化一般性原则 1)目标:减少服务器资源消耗(主要是磁盘IO) 2)设计: 1. 尽量依赖oracle优化器 2. 合适的索引(数据重复量大的列不要简历二叉树索引,可以使用位图索引: 对应数据操作频繁的表,索引需要定期重建,减少失效的索引和碎片) 3)编码: 1. 利用索引 2. 合理利用临时表 3. 避免写过于复杂的sql: 4. 尽量减小事务的粒度 2. 具体注意事项 1)查询时尽量使

Join的实现原理及优化思路

前言 前面我们已经了解了MySQLQueryOptimizer的工作原理,学习了Query优化的基本原则和思路,理解了索引选择的技巧,这一节我们将围绕Query语句中使用非常频繁,且随时可能存在性能隐患的Join语句,继续我们的Query优化之旅. Join 的实现原理 在寻找Join语句的优化思路之前,我们首先要理解在MySQL中是如何来实现Join的,只要理解了实现原理之后,优化就比较简单了.下面我们先分析一下MySQL中Join的实现原理. 在MySQL中,只有一种Join算法,就是大名鼎