程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 關於優化for循環的注意的事項,優化for循環事項

關於優化for循環的注意的事項,優化for循環事項

編輯:C#入門知識

關於優化for循環的注意的事項,優化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循環優化的只剩一個,這樣性能才能翻翻!

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved