我正在使用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);
有任何意见吗?
答案 0 :(得分:2)
我认为你不能比原始的jdbc调用更快。 如果你说你能用sql客户端更快地获取它,那么它是第一次尝试吗?客户端和数据库可以缓存结果,因此请在创建会话后检查从sql客户端运行第一个查询的时间。 同时发布java日志,这将有助于查看花费的时间。
答案 1 :(得分:2)
这不是JdbcTemplate的错。原因如下:
首先,您必须减少建立连接的开销。这个开销可能高达500毫秒。这是正常。
其次,当您在MySQL客户端上运行查询时,是否在运行程序后立即运行它?因为查询得到缓存......即使在磁盘I / O级别也是如此。因此,如果您运行相同的查询两次,则第二次由于缓存而运行得更快。
第三个,您是在为name
列编制索引吗?
第四个,如果连接开销对您来说真的很重要,您可以考虑保留连接甚至连接池。
答案 2 :(得分:0)
尝试增加获取大小(JdbcTemplate.setFetchSize),它可能是瓶颈。
答案 3 :(得分:0)
可能是建立第一个数据库连接的开销。在确定已经建立连接后尝试基准性能。
这些东西不应该慢,增益就在那里!