Java Spring jdbcTemplate queryForList慢

时间:2013-08-06 11:19:54

标签: java mysql spring jdbctemplate

我正在使用Spring jdbcTemplate在我的java应用程序中运行MySQL查询。这是我的功能:

public static ArrayList<Map<String, Object>> query(String q) throws Exception {

    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);

    @SuppressWarnings("unchecked")
    List<Map<String, Object>> result = jdbcTemplate.queryForList(q);

    return (ArrayList<Map<String, Object>>) result;

}

在这种特殊情况下,我传递了这个查询的函数:

"SELECT * FROM test WHERE name IN('string1', 'string2', 'string3', ...)";

test只有6列,IN中的字符串从几个到100个不等。 jdbcTemplate.queryForList()需要 280毫秒才能运行查询。注意:jdbcTemplate.queryForList()运行需要280毫秒,而不是整个函数query。当我在MySQL客户端(HeidiSQL)上运行完全相同的查询时,它只需 16毫秒更新: Heidi保持开放式连接,因此这不是一个公平的比较。

问题:与在MySQL客户端上运行的相同查询相比,为什么jdbcTemplate.queryForList()如此缓慢?我纯粹是出于便利的原因使用它,它可以检索ArrayList<Map<String, Object>>中的结果,这是我需要的。我有什么办法可以加快速度吗?或者我应该把jdbcTemplate放在一起并使用别的东西吗?

UPDATE:好的,所以我已经将我的函数从jdbcTemplate更改为使用普通的jdbc。这就是令人憎恶的样子。这就是为什么我首先使用jdbcTemplate。运行相同的查询现在需要 200毫秒 - 略有改进,但仍然太慢......

public static ArrayList<Map<String,Object>> query(String Full_Command) {

    try {

        String URL = "jdbc:mysql://localhost/dbname";
        String USER = "root";
        String PASS = "";
        java.sql.Connection Con = DriverManager.getConnection(URL, USER, PASS);

        //create statement
        Statement Stm = null;
        //Stm = Con.createStatement();
        Stm = (Statement) Con.createStatement();

        //query
        ResultSet Result = null;
        boolean Returning_Rows = Stm.execute(Full_Command);
        if (Returning_Rows) {
            Result = Stm.getResultSet();
        } else {
            return new ArrayList<Map<String,Object>>();
        }

        //get metadata
        ResultSetMetaData Meta = null;
        Meta = Result.getMetaData();

        //get column names
        int Col_Count = Meta.getColumnCount();
        ArrayList<String> Cols = new ArrayList<String>();
        for (int Index=1; Index<=Col_Count; Index++) {
            Cols.add(Meta.getColumnName(Index));
        }

        //fetch out rows
        ArrayList<Map<String, Object>> Rows = new ArrayList<Map<String,Object>>();

        while (Result.next()) {
            HashMap<String,Object> Row = new HashMap<String,Object>();
            for (String Col_Name:Cols) {
                Object Val = Result.getObject(Col_Name);
                Row.put(Col_Name,Val);
            }
            Rows.add(Row);
        }

        //close statement
        Stm.close();

        //pass back rows
        return Rows;

    } catch (Exception Ex) {

        System.out.print(Ex.getMessage());
        return new ArrayList<Map<String,Object>>();

    }

}

UPDATE2:我没有将JDBC功能分解为执行时间,而这一行是瓶颈,每次花费约190毫秒:

java.sql.Connection Con = DriverManager.getConnection(URL, USER, PASS);

有任何意见吗?

4 个答案:

答案 0 :(得分:2)

我认为你不能比原始的jdbc调用更快。 如果你说你能用sql客户端更快地获取它,那么它是第一次尝试吗?客户端和数据库可以缓存结果,因此请在创建会话后检查从sql客户端运行第一个查询的时间。 同时发布java日志,这将有助于查看花费的时间。

答案 1 :(得分:2)

这不是JdbcTemplate的错。原因如下:

首先,您必须减少建立连接的开销。这个开销可能高达500毫秒。这是正常

其次,当您在MySQL客户端上运行查询时,是否在运行程序后立即运行它?因为查询得到缓存......即使在磁盘I / O级别也是如此。因此,如果您运行相同的查询两次,则第二次由于缓存而运行得更快。

第三个,您是在为name列编制索引吗?

第四个,如果连接开销对您来说真的很重要,您可以考虑保留连接甚至连接池。

答案 2 :(得分:0)

尝试增加获取大小(JdbcTemplate.setFetchSize),它可能是瓶颈。

答案 3 :(得分:0)

可能是建立第一个数据库连接的开销。在确定已经建立连接后尝试基准性能。

这些东西不应该慢,增益就在那里!