优化系列

在调优网站  http://www.kdsw.cn/ 的过程中碰到的问题

 

1 StringBufferString的天差地别

例子

这是我在该项目中查导出文件很慢的原因时察觉到的一个问题 当时客户问我们导出怎么这么久 吓死我了

//初始化导出文件内容

       

        String outStr =new String ("");

        //数据行数

        int lines = data.length;

        for (int i = 0; i < lines; i++)

        {

            //数据列数

            int columns = data[i].length;

            for(int j = 0; j < columns; j++)

            {

                if (data[i][j] == null)

                {

                    data[i][j] = "";

                }

                //将每列数据中的替换

                if ( data[i][j].indexOf(',') >= 0)

                {

                    int strLen = data[i][j].length();

                    int pos = 0;

                    while (pos >= 0 && pos < strLen)

                    {

                        pos = data[i][j].indexOf(',', pos);

                        if (pos >= 0)

                        {

                            data[i][j] = data[i][j].substring(0,pos) + "" + data[i][j].substring(pos + 1);

                        }

                    }

                }

                outStr+= (data[i][j]);

                //如果不是每行的最后一列,用号将数据分隔

                if (j < columns - 1)

                {

                      outStr+=(",");

                }

            }

            //每行加一个换行

            outStr+= ("/n");

        }

   假如现在data[i][j]的大小事 data[10000][10] 也就是说二维数组有

10000  10 假如数据显示如下

Id  name  sex age uid           pwd             pic     tilte    content desc

1   廖敏       22 liaomin789  liaomin999    图片大家好   你们好情况 好啊

1   胡群       21 liaomin789  liaomin999    图片大家好   你们好情况 好啊

1   baby       22 liaomin789  liaomin999    图片大家好   你们好情况 好啊

。。。。。。。

 

通过执行 上面一段代码 结果就会形成一个很长的字符串

猜一下 上面代码 需要执行多久   结果是 30分钟,客户足足等了30分钟 才出来

仍然是上面的数组  代码改成下面

//初始化导出文件内容

        StringBuffer outStr =new StringBuffer("");

       

 

        //数据行数

        int lines = data.length;

       

       

        for (int i = 0; i < lines; i++)

        {

            //数据列数

            int columns = data[i].length;

            for(int j = 0; j < columns; j++)

            {

                if (data[i][j] == null)

                {

                    data[i][j] = "";

                }

                //将每列数据中的替换

                if ( data[i][j].indexOf(',') >= 0)

                {

                    int strLen = data[i][j].length();

                    int pos = 0;

                    while (pos >= 0 && pos < strLen)

                    {

                        pos = data[i][j].indexOf(',', pos);

                        if (pos >= 0)

                        {

                            data[i][j] = data[i][j].substring(0,pos) + "" + data[i][j].substring(pos + 1);

                        }

                    }

                }

                outStr.append(data[i][j]);

                //如果不是每行的最后一列,用号将数据分隔

                if (j < columns - 1)

                {

                      outStr.append(",");

                }

            }

            //每行加一个换行

            outStr.append("/n");

        }

猜一下 需要执行多久   结果是5

不可思议吧  这就是string stringbuffer之间的差别

为什么了 

因为String类型的字符串本身是不可修改的

你操作一次  内存中就会多了一个String 类型的数据

上面一个数组 循环 10000*10 操作了将近 10

所以总共参数 1000000String对象 内存怎么容得下  何其庞大

StringBuffer 操作的对象本身 从头到尾就一个对象 所以速度

非常的快

 

2 与数据库交互的次数

在网站发送短信 时碰到的问题

看下面代码

List<IosSmSendBO> smSendBOList = (List<IosSmSendBO>)sendService.getSendBoxList(queryBO);

for (int i = 0; i < smSendBOList.size(); i++)

                        {

                              IosSmSendBO sendBO = smSendBOList.get(i);

                              // add by ZouJing at Jun 17, 2009

 

                              // 操作黑名单短信

                              query.setGroupId(sendBO.getGroupId());

                              query.setMobileNo(sendBO.getReceiverCode());

                              if(iosSmBlackAddrService.isBlackAddr(query))

                              {

                                    sendBO.setStatus("0");

                                    // 失败原因

                                    sendBO.setSendFailReason("号码:"

                                                + sendBO.getReceiverCode()

                                                + "是黑名单号码,禁止发送!");

                                    Logger.getLogger(this.getClass()).info(

                                                "号码:" + sendBO.getReceiverCode()

                                                            + "是黑名单号码,禁止发送!");

                                    // 发送时间

                                    sendBO.setSendTime(DateTimeFormat.FormatDateToString(

                                                new Date(), DateTimeFormat.DATE_WITH_TIME));

 

                                    // 新增发送短信记录及在发送后修改后改变状态

                                    sendService.updateIosSmSend(sendBO);

                                    continue;

                              }

                             

                              // 设置内外网号码

                      IosBuyInfoBO buyInfoBO = new IosBuyInfoBO();

                      buyInfoBO.setGroupId(sendBO.getGroupId());

                      List<IosBuyInfoBO> buyList = buyInfoService.getIosBuyInfoBOs(buyInfoBO);

                      sendBO.setExternalValueIn(buyList.get(0).getExternalValueIn());

                      sendBO.setExternalValueOut(buyList.get(0).getExternalValueOut());

                     

                      //取出发送用户的信息

                      IosPersonInfoBO userInfo = new IosPersonInfoBO();

                      userInfo.setOid(sendBO.getCreatedBy());

                   List<IosPersonInfoBO> personInfoList = personInfoService.queryCorpLists(userInfo, false);

                      if (personInfoList != null && personInfoList.size() > 0) {

                                    IosPersonInfoBO personInfo = personInfoList.get(0);

                                    //集团签名

                                    String groupId = personInfo.getGroupId();

                                    IosGroupInfoBO groupInfoBO = new IosGroupInfoBO();

                                    groupInfoBO.setGroupId(groupId);

                                    List<IosGroupInfoBO> groupInfoBOList = groupInfoService.getIosGroupInfoBOs(groupInfoBO);

                                    if (groupInfoBOList != null && groupInfoBOList.size() > 0)

                                    {

                                          sendBO.setGroupName(groupInfoBOList.get(0).getGroupName());

                                         

                                  //add by hezhenbo at 2009-06-13

                                  sendBO.setBossId(groupInfoBOList.get(0).getBossId());

}                

}

 

假如 List<IosSmSendBO> smSendBOList = (List<IosSmSendBO>)sendService.getSendBoxList(queryBO);

取出smSendBOList的数据是 2000

 

在循环取出smSendBOList数据 进行验证

在循环体内部代码

iosSmBlackAddrService.isBlackAddr(query) //判断是否是黑名单

List<IosPersonInfoBO> personInfoList = personInfoService.queryCorpLists(userInfo, false); //取出接受信息人

List<IosGroupInfoBO> groupInfoBOList = groupInfoService.getIosGroupInfoBOs(groupInfoBO);//取出接受人组信息

这些都是在进行数据库查询 每次调用一次都会打开一次数据库连接

打开数据库连接 一次需要 50ms 尚且不考虑内存消耗,调用三次有 150ms

2000次循环  需要300000ms 需要300s

兄弟 你想 加入 批量发送2000条信息  需要300s  也就是5分钟 人家等 5分钟啊

所以 是行不通的

 

假如我将那些数据批量取出放到内存中

只需要调用三次

测试  调用一次 取出所有满足条件数据3s

调用 三次 9s  内存中循环操作处理 大概 2s

只需 11s

11s  相对于 300s  是何其壮观啊

 

这就是批量与不批量的差别

 

 

3 内外连接

加入数据库中 20w条数据  plsql中执行

查询所有数据

内连接

 

select * from ios_self_addresslist isa, ios_self_team_rel istr, ios_self_team ist

                                    where isa.oid = istr.self_adl_id and ist.oid = istr.team_id

                                    and isa.stop_flag = 0 and istr.stop_flag=0

耗时 0.046s

 

左连接

select * from ios_self_addresslist isa left join ios_self_team_rel istr on isa.oid = istr.self_adl_id

       left join  ios_self_team ist on ist.oid = istr.team_id

                                     where  isa.stop_flag = 0 and istr.stop_flag=0

耗时1.813s

 

查询所有总数

内连接

 

select * from ios_self_addresslist isa, ios_self_team_rel istr, ios_self_team ist

                                    where isa.oid = istr.self_adl_id and ist.oid = istr.team_id

                                    and isa.stop_flag = 0 and istr.stop_flag=0

耗时 1.078s

左连接

select * from ios_self_addresslist isa left join ios_self_team_rel istr on isa.oid = istr.self_adl_id

       left join  ios_self_team ist on ist.oid = istr.team_id

                                     where  isa.stop_flag = 0 and istr.stop_flag=0

耗时 1.063

转载于:https://www.cnblogs.com/liaomin416100569/archive/2009/12/18/9332061.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值