灯火互联
管理员
管理员
  • 注册日期2011-07-27
  • 发帖数41778
  • QQ
  • 火币41290枚
  • 粉丝1086
  • 关注100
  • 终身成就奖
  • 最爱沙发
  • 忠实会员
  • 灌水天才奖
  • 贴图大师奖
  • 原创先锋奖
  • 特殊贡献奖
  • 宣传大使奖
  • 优秀斑竹奖
  • 社区明星
阅读:2601回复:0

java中使用SQL的效率分析例子

楼主#
更多 发布于:2012-09-08 09:39


前年给地图技术审查中心做了一个培训的报名系统,功能需求比较简单,由于当时刚开始摸索java就只能照葫芦画瓢的使用JDBC写的程序。这是中百信公司的遗留项目,我接手过来的,仿照以前的代码写得。
出现问题的代码:
[html]
<div id="content">
            <div class="locbackground">
            </div>
            <div class="text">
            <center>
                <h1>
                    查看培训(会议)报名信息
                </h1>
                <div><input type="button" value="导出会议(培训)报名信息 "cid")%>'"/></div>
                <br/><table class="listCases" width="100%" border="0"
                    style="width: 100%; FONT-SIZE: 18px; word-break: break-all"
                    cellspacing="1" cellpadding="5" bgcolor=#455ca2>
                    <thead>
                        <tr height="40px">
                            <th width="70" bgcolor=#dcdcdc align="center" class=""
                                style="font-size: 14px; FONT-WEIGHT: bold">
                                操作
                            </th>
                            <th width="30" bgcolor=#dcdcdc align="center" class=""
                                style="font-size: 14px; FONT-WEIGHT: bold">
                                序号
                            </th>
                            <th width="30" bgcolor=#dcdcdc align="center" class=""
                                style="font-size: 14px; FONT-WEIGHT: bold">
                                姓名
                            </th>
                            <th bgcolor=#dcdcdc align="center" class=""
                                style="font-size: 14px; FONT-WEIGHT: bold">
                                性别
                            </th>
                            <th bgcolor=#dcdcdc align="center" class=""
                                style="font-size: 14px; FONT-WEIGHT: bold">
                                民族
                            </th>
                            <th bgcolor=#dcdcdc align="center" class=""
                                style="font-size: 14px; FONT-WEIGHT: bold">
                                身份证号
                            </th>
                            <th bgcolor=#dcdcdc align="center" class=""
                                style="font-size: 14px; FONT-WEIGHT: bold">
                                工作单位
                            </th>
                            <th bgcolor=#dcdcdc align="center" class=""
                                style="font-size: 14px; FONT-WEIGHT: bold">
                                职务(职称)
                            </th>
                            <th bgcolor=#dcdcdc align="center" class=""
                                style="font-size: 14px; FONT-WEIGHT: bold">
                                手机号码
                            </th>
                            <th bgcolor=#dcdcdc align="center" class=""
                                style="font-size: 14px; FONT-WEIGHT: bold">
                                乘坐何种 交通工具(班次)
                            </th>
                            <th bgcolor=#dcdcdc align="center" class=""
                                style="font-size: 14px; FONT-WEIGHT: bold">
                                到达时间
                            </th>
                            <th bgcolor=#dcdcdc align="center" class=""
                                style="font-size: 14px; FONT-WEIGHT: bold">
                                注册时间
                            </th>
                            <th bgcolor=#dcdcdc align="center" class=""
                                style="font-size: 14px; FONT-WEIGHT: bold">
                                ip地址
                            </th>
                        </tr>
                    </thead>
                    <%
                        Collection registerId = conferenceRegisterAssignOp.getRegisterIdByConferenceId(Integer.parseInt(request.getParameter("cid")));
                        Iterator it = registerId.iterator();
                        int index = 1;
                        while (it.hasNext()) {
                            Integer integer = (Integer)it.next();
                            int rid = integer.intValue();
                            Register temp = registerOp.getCaseInfo(rid);
                    %>
                    <tr>
                        <td class="listContent">
                            <a href="dtsc/pxbm/editRegister.jsp?registerId=<%=temp.getId()%>">编辑</a>
                            <br />
                            <br />
                            <a href="dtsc/pxbm/deleteRegister.jsp?registerId=<%=temp.getId()%>">删除</a>
                            <br />
                            <br />
                            <a href="dtsc/pxbm/editRegister.jsp?registerId=<%=temp.getId()%>">查看详细</a>
                        </td>
                        <td class="listContent"><%=index%></td>
                        <td class="listContent"><%=temp.getName() %></td>
                        <td class="listContent"><%=CodeSet.getSex(temp.getSex())%></td>
                        <td class="listContent"><%=temp.getRace()%></td>
                        <td class="listContent"><%=temp.getIdentificationId() %></td>
                        <td class="listContent"><%=temp.getDepartment()%></td>
                        <td class="listContent"><%=temp.getPositionOrIdentity()%></td>
                        <td class="listContent"><%=temp.getMobilephone()%></td>
                        <td class="listContent"><%=temp.getDeparture()%></td>
                        <td class="listContent"><%=temp.getArrivingTime()%></td>
                        <td class="listContent"><%=temp.getRegisterTime()%></td>
                        <td class="listContent"><%=temp.getIp()%></td>
                    </tr>
                    <%
                        ++index;
                        }
                    %>
                </table>
                </center>
            </div>
        </div>
因为是嵌在JSP页面的中代码,在java代码后面跟的是一些显示用的HTML代码。
注意这一段代码:
[javascript]
Collection registerId = conferenceRegisterAssignOp.getRegisterIdByConferenceId(Integer.parseInt(request.getParameter("cid")));
                    Iterator it = registerId.iterator();
                    int index = 1;
                    while (it.hasNext()) {
                        Integer integer = (Integer)it.next();
                        int rid = integer.intValue();
                        Register temp = registerOp.getCaseInfo(rid);
这里边先根据cid(培训会议表id)取到了参加本次会议的注册人员的id列表。
[javascript]
<pre name="code" class="java">Collection registerId = conferenceRegisterAssignOp.getRegisterIdByConferenceId(Integer.parseInt(request.getParameter("cid")));
然后再遍历这个列表,对每一个注册人员id,都取出这个人员的详细信息。
[java]
Register temp = registerOp.getCaseInfo(rid);
这样在报名的数量达到200条的时候运行起来的时间大约为40s到70秒s。由于这个页面的table中的行tr是在后台逐条生成的,再Collection遍历是陆陆续续发送到浏览器的,这样会使浏览器等待页面的时间太长,导致浏览器与后台web Server的连接超过TimeOut时长,断开连接。反应到前端浏览器的现象就是页面的前半部分加载完成,列表没有全部加载出来。
改进的代码:
原因分析清楚之后,我们需要改进这个查找机制,需要把这两次操作合并到一次SQL查询中完成,让SQL在后台一次就把我们需要的注册人员的详细信息查询出来。
[java]
Collection registers = conferenceRegisterAssignOp.getRegistersByConferenceId(Integer.parseInt(request.getParameter("cid")));
                            Iterator it = registers.iterator();
                            int index = 1;
                            while (it.hasNext()) {
                                Register temp = (Register)it.next();
在这里,我只用了一次查询:
[java]
getRegistersByConferenceId就取出来了所有的注册信息。这个函数是这样写的:
[java]
<pre name="code" class="java">//根据会议Id获得参加会议的报名情况
    public Collection<Register> getRegistersByConferenceId(int conferenceId) throws Exception
    {
        Statement stmt=con.createStatement();
        ResultSet rst=stmt.executeQuery("SELECT     dtsc_register.id, dtsc_register.name, dtsc_register.sex, dtsc_register.age, dtsc_register.race,"+  
                      "dtsc_register.identificationId, dtsc_register.department, dtsc_register.positionOrIdentity, dtsc_register.mobilephone,"+  
                      "dtsc_register.departure, dtsc_register.arrivingTime, dtsc_register.ip, dtsc_register.registerTime, dtsc_register.education,"+  
                      "dtsc_register.address, dtsc_register.zipcode, dtsc_register.suozaibumen, dtsc_register.telephone, dtsc_register.isFirst "+
                      "FROM         dtsc_conferenceRegisterAssign INNER JOIN "+
                      "dtsc_register ON dtsc_conferenceRegisterAssign.registerId = dtsc_register.id "+
                      "WHERE     dtsc_conferenceRegisterAssign.conferenceId = "+conferenceId+" ORDER BY dtsc_conferenceRegisterAssign.id");
        Collection<Register> registers = new ArrayList<Register>();
        while (rst.next()) {
            Register register=new Register();
            register.setId(rst.getInt("id"));
            register.setName(rst.getString("name"));
            register.setSex(rst.getInt("sex"));
            register.setRace(rst.getString("race"));
            register.setIdentificationId(rst.getString("identificationId"));
            register.setDepartment(rst.getString("department"));
            register.setPositionOrIdentity(rst.getString("positionOrIdentity"));
            register.setMobilephone(rst.getString("mobilephone"));
            register.setDeparture(rst.getString("departure"));
            register.setArrivingTime(rst.getString("arrivingTime"));
            register.setIp(rst.getString("ip"));
            register.setRegisterTime(rst.getString("registerTime"));
            register.setEducation(rst.getString("education"));
            register.setAddress(rst.getString("address"));
            register.setZipcode(rst.getString("zipcode"));
            register.setSuozaibumen(rst.getString("suozaibumen"));
            register.setTelephone(rst.getString("telephone"));
            register.setIsFirst(rst.getInt("isFirst"));
            registers.add(register);        
        }
        con.close();
        return registers;

    }
通过INNER JOIN就可以通过一次数据库的查询达到目的。
结论:
对比前后两种代码,我们看到,对数据库的操作次数越少越好。如前面我们总共进行了<本次会议报名人数+1>次数据库查询,后着我们只进行了一次Inner Join查询操作。差距显而易见。所以在表之间靠外键进行联系时,如果你用原始的JDBC语句,请一次完成查询。
如果你使用的是HIbernate这样的ORM框架,那么恭喜你,你不用为构造复杂的SQL而操心,她内部的多层缓存机制和Lazy懒惰机制会使你最少的进行数据库查询(当然你需要了解更多的配置才行),大大提高效率。


喜欢0 评分0
游客

返回顶部