IN子句效率中的preparedstatement设置值

Posted

技术标签:

【中文标题】IN子句效率中的preparedstatement设置值【英文标题】:preparedstatement setting values in IN clause efficiency 【发布时间】:2015-01-09 06:29:42 【问题描述】:

代码应该是独立于数据库的,所以我使用的是普通的 sql。

我的查询可以在运行时更改,例如 table1 更改为 table2。 但是假设对于 table1 查询,我必须更新 2000 条记录,其中插槽为 50,这意味着一旦处理了 50 条记录,我就会提交。

我有两种方法可以在 sql 语句的 IN 子句中设置值。 我想知道下面哪个代码效率更高(priority is optimization and maintainability is secondary)?

PreparedStatement preparedStatement = sqlObj.prepareStatement(
    "UPDATE table1 column1=? WHERE table_id IN (" + StringUtils.repeat("?,", paramArray.length-1)+ "?)");
preparedStatement.setInt(1, 0);
for(int idx = 0; idx < paramArray.length; idx++) 
    preparedStatement.setInt(idx+2, paramArray[idx]);

preparedStatement.executeQuery();

或者

PreparedStatement preparedStatement = sqlObj.prepareStatement(
    "UPDATE table1 column1=? WHERE table_id IN (?)");
for(int idx = 0; idx < paramArray.length; idx++) 
    preparedStatement.setInt(1, 0);
    preparedStatement.setInt(2, paramArray[idx]);

    preparedStatement.addBatch();

preparedStatement.executeBatch();

编辑: 假设param.length is 50 和整个代码exectutes 40 times 即处理2000 records

所以在第一种情况下它会附加 50 ?然后为他们设置变量进行一个更新查询,在第二种情况下,它将创建一批 50 个更新查询。

【问题讨论】:

如果您只调用一次或很少调用代码,那么第一个。否则,这取决于您进行相同更新的频率、每次包含多少参数以及数据库的语句缓存。 我已经更新了我的问题。 【参考方案1】:

似乎第二次你根本不需要 IN,你可以使用 WHERE table_id = ?因为您每次设置 1 个值。 在这种情况下,第二个会更快,因为您将使用 Batch。

请看 Why are batch inserts/updates faster? How do batch updates work?

如果您使用的是 Oracle,您还可以执行类似的操作

create or replace TYPE "NUMBER_ARRAY" IS TABLE OF NUMBER(18,0);   

在 Java 代码中

PreparedStatement preparedStatement = sqlObj.prepareStatement(
"UPDATE table1 column1=? WHERE table_id IN (SELECT column_value FROM TABLE (CAST(? AS number_array)))");    
JdbcUtils.setArray(2, tableIds.toArray(new Long[tableIds.size()]), ps);    

【讨论】:

提问者正在请求数据库独立代码。 @Peter,在我提到数据库独立性之前已经给出了答案。 啊,好吧,所以@prsmax:对不起:)【参考方案2】:

第一种方法导致为每次调用重新创建准备好的语句,因此不需要准备好的语句。第二个可以预编译和重用。这是主要区别:您的第二种方法允许您重用查询对象并省略查询解析。 编辑:对不起,读得太快了。绑定多个参数显然比绑定一个参数效率低。

【讨论】:

你能澄清一下这个“所以there is no need for a prepared statement”,我应该用什么来代替准备好的声明。 不,我只是读得快而且不完整。请参阅“已编辑” - 响应的一部分。您的第二种方法确实取决于您要绑定的只有两个参数,因此您的语句之间的主要区别在于批处理。这并不是真正需要的,因为您只发送一个命令(sql 查询)。 您是想说绑定 50 个变量效率低下,然后设置批量 50 个 sql 更新语句。我对您的回答的理解是否正确?【参考方案3】:

如果这只是出于好奇而提出的问题,我会说它更多地取决于数据库而不是准备好的语句。数据库操作比移动一些字节要昂贵得多。

如果你问这个问题是因为你想让你的应用程序更快,我不得不问这个更新是否真的是一个性能瓶颈。你量过吗?

如果这不是性能瓶颈,并且您想优化以防万一:不要。拥有可维护的代码比优化非关键代码更重要。使用复杂度最低且最容易理解的变体:变体 2。

【讨论】:

非常感谢您的回答方式。上面的代码是示例代码,但它代表了我的应用程序中的代码。现在我的首要任务是优化,可维护性是次要的..

以上是关于IN子句效率中的preparedstatement设置值的主要内容,如果未能解决你的问题,请参考以下文章

PreparedStatement IN子句Regexp替代?

如何使用 WHERE x IN 子句为 PreparedStatement 编写 SQL?

JDBC中的PreparedStatement

PreparedStatement 可以不考虑 WHERE 子句中的某些条件吗?

MySql in子句 效率低下优化(亲测有效,从200秒变1秒)

PreparedStatement 没有?在 where 子句中