使用不同的参数多次运行相同的选择查询:Mysql

时间:2013-04-05 19:15:12

标签: java mysql select jdbc prepared-statement

我有一个java程序,需要迭代HashMap来获取一个参数,然后用于查询MySQL数据库。

代码如下:

Iterator<Entry<String, Double>>it = ws.entrySet().iterator();
Connection con = null;

while(it.hasNext())  
{
    Entry<String, Double>pairs = it.next();
    PreparedStatement ps = con.prepareStatement("select doc_freq from lookup where word=?");
    ps.setString(1, pairs.getKey());
    ResultSet rs = ps.executeQuery();
}

循环的每次迭代(大约500次)重复访问数据库的过程正在减慢我的应用程序。有没有什么方法可以一次发送所有这些参数,以便我只访问数据库一次?

3 个答案:

答案 0 :(得分:1)

考虑到ws是一张地图,你可以这样做:

Connection con = getConnection();
Set<String> ks = ws.keySet();

if (ks.size() > 0) {
    StringBuilder inStatement = new StringBuilder("?");
    for (int i = 1; i < ks.size(); i++) {
        inStatement.append(", ?");
    }

    PreparedStatement ps = con.prepareStatement("select doc_freq from lookup where word in (" + inStatement.toString() + ")");

    int k = 1;
    for (String key : keySet) {
        ps.setString(k++, key);
    }
    ResultSet rs = ps.executeQuery();
}

答案 1 :(得分:0)

准备语句一次然后迭代并设置参数然后执行。这是来自javadoc

  

可以预编译带有或不带IN参数的SQL语句   存储在PreparedStatement对象中。然后可以使用该对象   多次有效地执行此语句。   此方法针对处理参数化SQL语句进行了优化   受益于预编译。如果驱动程序支持预编译......

Iterator<Entry<String, Double>>it = ws.entrySet().iterator();
Connection con = getConnection();

PreparedStatement ps = con.prepareStatement("select doc_freq from lookup where word=?");
while(it.hasNext())  
{
    Entry<String, Double>pairs = it.next();
    ps.setString(1, pairs.getKey());
    ResultSet rs = ps.executeQuery();
}

好的,我会解释一下。当查询被编译到db时,它使得逐个执行和检索结果变得更快,这与执行具有多个参数的一个查询相同。表现是平等的。但是如果你准备,编译相同的SQL查询多个类型,db每次编译查询时都会创建执行计划,这是时间令人反感的。这就是为什么这种技术在文档中称为高效。该术语也称为解释计划,它由db创建,以更好地优化查询。

答案 2 :(得分:0)

问题不清楚为什么它很慢但一个常见的问题是每笔交易的开销。

您可以将innodb_flush_log_at_trx_commit设置为0或2,一切都会更快。但请注意,默认值1是唯一符合ACID的设置。对于大多数设置,2是一个非常好的值。

set global innodb_flush_log_at_trx_commit = 2;