没有绑定变量的PreparedStatement会影响性能吗?

时间:2016-07-21 09:05:00

标签: java

如果我不在预准备语句中使用绑定变量,性能是否会降低。

考虑以下示例:

String selectSQL = "SELECT USER_ID, USERNAME FROM DBUSER WHERE USER_ID = '101'";
PreparedStatement preparedStatement =     dbConnection.prepareStatement(selectSQL);
我知道,下面一个是优选的。 它阻止了sql注入

String selectSQL = "SELECT USER_ID, USERNAME FROM DBUSER WHERE USER_ID = ?";

这个问题是因为我的所有查询中的一个项目都有硬编码的字符串文字,即使他们使用的是准备好的语句。

2 个答案:

答案 0 :(得分:2)

准备好的陈述只是意味着你准备好了#34;该声明。这意味着您将其发送到数据库并让数据库已经解析/编译该语句。这对于经常执行的语句很有用。

参数化语句经常被执行多次,因此它们有时与预准备语句相关联(您只需要发送值,服务器将有一个已编译的语句准备好执行查询)。

但即使使用"静态"通常执行的语句可能会从准备语句中受益(特别是对于"复杂的#34;语句)。使用的另一种技术是在存储过程内实现查询。这样,查询已经编译,服务器只需要在运行时编译存储过程调用。

只有在你没有做好准备时(例如关闭连接时),它才会起作用。因此,您可能需要一个池和一个预准备语句缓存,以便不使用预准备语句请求溢出服务器(预准备语句需要服务器上的资源结束)

参数化查询还用于防止sql注入(因为它基于数据类型而不是字符串)。然而,这与准备好的陈述的好处是正交的。 (注意你的查询都没有暴露给sql注入)

答案 1 :(得分:2)

使用参数是否更有效主要取决于您的使用案例。当你监控准备和执行语句所花费的时间时,你会注意到,语句的准备时间比实际执行的成本高得多,所以这取决于你是否可以节省准备。

你将永远赢得这样的场景:

PreparedStatement stmt = dbConnection.prepareStatement(...);
stmt.setInt(1, x);
stmt.executeQuery();
...
stmt.setInt(1, y);
stmt.executeQuery();
...

因为你节省了准备时间。这与DBMS无关。

某些DBMS执行一些服务器端缓存。他们做什么以及如何做是高度供应商甚至版本特定的。但是,我们已经了解到,在Oracle-DBMS中,更常使用的参数化语句有时会在这种情况下加速:

PreparedStatement stmt = dbConnection.prepareStatement(...);
stmt.setInt(1, x);
stmt.executeQuery();
...
PreparedStatement stmt2 = dbConnection.prepareStatement(...);
stmt2.setInt(1, y);
stmt2.executeQuery();
...

此处服务器能够识别两个语句基本相同,并且第二个语句的准备时间显着减少。这对固定字符串语句不起作用,因为服务器无法确定,它们是相同的。

我不认为,你会发现一个场景,使用参数化语句的可测量速度比固定字符串语句慢,但是很多场景,反之亦然。