java - JdbcDao支持queryForList慢

标签 java mysql spring

我正在尝试制作一个简单的 servlet 来使用 spring 框架 JdbcDaoSupport 显示数据库中的一些数据。执行一个“SELECT”-sql 命令大约需要 25-35 秒。我对 Spring 还很陌生,我不明白为什么要花这么长时间......

这是我的代码: BeanBox.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:c="http://www.springframework.org/schema/c"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:lang="http://www.springframework.org/schema/lang"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:util="http://www.springframework.org/schema/util"

       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
          http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
          http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
          http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.2.xsd
          http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
          http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd
">

        <!-- Data access related beans-->
    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location">
            <value>Settings.properties</value>
        </property>
    </bean>

    <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${db.driverClassName}" />
        <property name="url" value="${db.url}" />
        <property name="username" value="${db.user}" />
        <property name="password" value="${db.password}" />
        <property name="initialSize" value="8" />
    </bean>

    <bean id="productAnalyticsDAO" class="productAnalyticsDAO">
        <property name="dataSource" ref="dataSource" />
    </bean>

</beans>

products.java(实际的 servlet)

public class products extends HttpServlet {

    /**
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code>
     * methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("start:" + System.nanoTime());

        response.setContentType("text/html;charset=UTF-8");
        ApplicationContext context = new ClassPathXmlApplicationContext("BeanBox.xml");

        System.out.println("context created from xml:" + System.nanoTime());
        productAnalyticsDAO productDAO  = (productAnalyticsDAO) context.getBean("productAnalyticsDAO");

        System.out.println("getbean for the DAO:" + System.nanoTime());
        String interval = request.getParameterMap().isEmpty()? "today" : request.getParameter("t");

        System.out.println("fetch time parameter from request:" + System.nanoTime());

        try (PrintWriter out = response.getWriter()) {
            /* TODO output your page here. You may use following sample code. */
            out.println("<!DOCTYPE html>");
            out.println("<html>");
            out.println("<head>");
            out.println("<title>Servlet products</title>");            
            out.println("</head>");
            out.println("<body>");
            out.println("<h1>Product analytics : " + interval.toUpperCase() + "</h1>");
            out.println("<a href=\"products?t=today\">Today</a>, ");
            out.println("<a href=\"products?t=1D\">Yesterday</a>, ");
            out.println("<a href=\"products?t=WEEKEND\">Weekend</a>, ");
            out.println("<a href=\"products?t=1W\">1 Week</a>, ");
            out.println("<a href=\"products?t=1M\">1 Month</a>, ");
            out.println("<a href=\"products?t=3M\">3 Month</a>, ");
            out.println("<a href=\"products?t=YTD\">Year To Date</a>, ");
            out.println("<a href=\"products?t=1Y\">1 Year</a>, ");
            out.println("<a href=\"products?t=3Y\">3 Year</a>");
            out.println("<table>");
            System.out.println("HTML print 1:" + System.nanoTime());
            List sales = productDAO.getProducts(interval);
            System.out.println("Fetched sqles list:" + System.nanoTime());
            for (Iterator iterator = sales.iterator(); iterator.hasNext();) {
                out.println("<tr>");
                LinkedCaseInsensitiveMap next = (LinkedCaseInsensitiveMap) iterator.next();
                out.println("<td>" + next.get("REFERENCE") + "</td>");
                out.println("<td>" + next.get("NAME") + "</td>");
                out.println("<td>" + next.get("UNITS") + "</td>");
                out.println("</tr>");
            }
            System.out.println("Print data:" + System.nanoTime());
            out.println("</table>");
            out.println("</body>");
            out.println("</html>");
        }
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /**
     * Handles the HTTP <code>GET</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Handles the HTTP <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>

}

productAnalyticsDAO.java(数据访问对象)

public class productAnalyticsDAO extends JdbcDaoSupport {
    public List<String[]> getProducts(String interval){
        System.out.println("Entered getProducts:" + System.nanoTime());
        String sql = "SELECT PRODUCTS.REFERENCE, "
                + "PRODUCTS.NAME, "
                + "PRODUCTS.CATEGORY, "
                + "SUM(TICKETLINES.UNITS) AS UNITS, "
                + "SUM(TICKETLINES.UNITS * TICKETLINES.PRICE) AS TOTAL "
                + "FROM RECEIPTS, "
                + "TICKETS, "
                + "TICKETLINES, "
                + "PRODUCTS "
                + "WHERE RECEIPTS.ID = TICKETS.ID "
                + "AND TICKETS.ID = TICKETLINES.TICKET "
                + "AND TICKETLINES.PRODUCT = PRODUCTS.ID ";
                if(interval.equals("today")){
                    sql += "AND DATE(RECEIPTS.DATENEW)= CURDATE() ";
                }
                if(interval.equals("1D")){
                    sql += "AND DATE_SUB(CURDATE(),INTERVAL 1 DAY) <= DATE(RECEIPTS.DATENEW) ";
                }
                if(interval.equals("1W")){
                    sql += "AND DATE_SUB(CURDATE(),INTERVAL 1 WEEK) <= DATE(RECEIPTS.DATENEW) ";
                }
                if(interval.equals("WEEKEND")){
                    sql += "AND DATE_SUB(CURDATE(),INTERVAL 1 WEEK) <= DATE(RECEIPTS.DATENEW) ";
                    sql += "AND DAYOFWEEK(DATE(RECEIPTS.DATENEW))=1 OR DAYOFWEEK(DATE(RECEIPTS.DATENEW))=7 ";
                }
                if(interval.equals("1M")){
                    sql += "AND DATE_SUB(CURDATE(),INTERVAL 1 MONTH) <= DATE(RECEIPTS.DATENEW) ";
                }
                if(interval.equals("3M")){
                    sql += "AND DATE_SUB(CURDATE(),INTERVAL 3 MONTH) <= DATE(RECEIPTS.DATENEW) ";
                }
                if(interval.equals("YTD")){
                    sql += "AND YEAR(RECEIPTS.DATENEW)= YEAR(CURDATE()) <= DATE(RECEIPTS.DATENEW) ";
                }
                if(interval.equals("1Y")){
                    sql += "AND  DATE_SUB(CURDATE(),INTERVAL 1 YEAR) <= DATE(RECEIPTS.DATENEW) ";
                }
                if(interval.equals("3Y")){
                    sql += "AND  DATE_SUB(CURDATE(),INTERVAL 3 YEAR) <= DATE(RECEIPTS.DATENEW) ";
                }
                sql += "AND NOT PRODUCTS.CATEGORY = \"9286649c-00e1-428a-bd45-b47a1e0154b4\" " // filter out ophaal uren
                + "GROUP BY PRODUCTS.CATEGORY, PRODUCTS.NAME "
                + "ORDER BY PRODUCTS.NAME";

        System.out.println("Builded SQL string:" + System.nanoTime());
        List myBook = getJdbcTemplate().queryForList(sql);
        System.out.println("Fetched data:" + System.nanoTime());
        return myBook;
    }

我使用 System.nanoTime() 来计算不同点之间的弧:

  • 从 xml 创建的上下文:4943507136673
  • DAO 的 getbean:4943507261046//-> arc : 0.124373 毫秒
  • 从请求中获取时间参数:4943507687437//-> arc : 0.426391 毫秒
  • HTML print 1:4943507916077//-> arc : 0.228640 毫秒
  • 输入 getProducts:4943507993097//-> arc : 0.077020 毫秒
  • 构建的 SQL 字符串:4943508103467//-> arc : 0.110370 毫秒
  • 已获取数据:4980514095087//-> arc:37005.991620 毫秒
  • 获取的sqles列表:4980514152604//-> arc:0.057517毫秒
  • 打印数据:4980515844896//-> 弧:1.692292 毫秒

那么,为什么 getJdbcTemplate().queryForList(sql) 速度这么慢...... 数据库位于本地主机上,通过 phpMyAdmin 执行 sql 语句要快得多... 显示第 0 - 31 行(总共 32 行,查询花费了 0.1411 秒。)

编辑:执行的最终 SQL 命令为:SELECT PRODUCTS.REFERENCE, PRODUCTS.NAME, PRODUCTS.CATEGORY, SUM(TICKETLINES.UNITS) AS UNITS, SUM(TICKETLINES.UNITS * TICKETLINES.PRICE) AS TOTAL FROM RECEIPTS 、门票、TICKETLINES、产品,其中 RECEIPTS.ID = TICKETS.ID AND TICKETS.ID = TICKETLINES.TICKET AND TICKETLINES.Product = 产品.ID 和日期(RECEIPTS.DATENEW)= CURDATE() 而不是 Products.CATEGORY = "9286649c- 00e1-428a-bd45-b47a1e0154b4"按产品.类别、产品.名称分组 按产品.名称排序

谢谢你, 罗宾

最佳答案

  1. 一种可能性是查询的形成可能会减慢结果的速度 查询应该是这样的格式

    来自收据 左外联票 收据.ID = 门票.ID 左外联票线路 ON TICKETS.ID = TICKETLINES.TICKET 左外连接产品 ON TICKETLINES.PRODUCT = PRODUCTS.ID

  2. 您也可以尝试indexing这些列将使它运行得更快,但在评估后使用它

关于java - JdbcDao支持queryForList慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31623959/

相关文章:

javascript - 使用 Thymeleaf 将数据动态插入到 javascript 图表中

java - 当 Spring 看到 <task :annotation-driven/> in a webapp what contexts are checked?

java - 将 javabean 初始化为随机值的方法

Java Swing,所有图像均出现像素化

php - Mysql大数据库迁移

php - MySQL 5.6 需要很长时间才能连接,即使是 "MySQL 5.6 Command Line Client"

php - SQL 查询返回空值?

java - 从手机导入联系人以在 Android 中的我的应用程序中列出

java - 当 apache tomcat 作为 Windows 服务安装时,如何配置 apache tomcat 使用不同的 java home?

java - 更新到SDN 3.4.1后出现异常 "The Neo Server running is of unknown type."