PreparedStatement 在简单的静态方法查询中有何性能优势?

问题描述 投票:0回答:4

更新 2 否决票是应得的,并鼓励我编写一个更强大的测试:使用 java 1.8、ojdbc8.jar 针对非生产 Oracle 12C 数据库,我通常是该数据库的唯一用户, 我运行了 100 次选择的 10 次迭代:50 次使用PreparedStatement,50 次使用Statement(使用字符串连接构建查询)。 为了尝试排除某种数据库缓存,我再次运行测试,但交换了顺序,首先运行语句,然后运行PreparedStatements。 无论顺序如何,性能都没有显着差异。请参阅下面的结果(以毫秒为单位,包含平均值和标准差)。

更新:感谢您的所有意见。我更新了标题。我在研究这个问题时发现了很多陈词滥调(“PreparedStatements 总是更快”,“PreparedStatements 总是更慢”),但没有什么明确的,我最终编写了一个测试,发现在这种情况下,PreparedStatements 始终约为 25%慢一点。

最初的问题: 我有一个带有简单查询的静态方法,用于检查数据库中是否已存在 ID:

public static boolean isPersisted(Integer id) { String sql = "select id from table where id = "+id+"";
我知道它们可以防止 SQL 注入,并且我知道它们在循环插入带有 ID 列表的插入时提供了很大的好处(例如),但是,在这里使用准备好的语句是否有任何

性能/内存优势

java jdbc prepared-statement
4个回答
2
投票
在这里使用准备好的语句对性能/内存有什么好处吗?

当您必须使用不同的数据多次运行相同的语句时,准备好的语句要快得多。这是因为 SQL 只会验证查询一次,而如果您只使用语句,它每次都会验证查询。

有关原因和发生情况的详细信息可以在

这篇文章中找到


0
投票
如果查询仅执行一次,并且

id

 是为应用程序本身干净地生成的(例如作为简单的计算结果),则准备好的语句没有任何好处。

如果必须使用各种

id

 值多次执行查询,则使用准备好的查询将获得很高的性能增益,因为 SQL 引擎只会解析该查询一次。

如果

id

参数来自用户界面,则您
必须使用准备好的语句,除非您打算容易受到SQL注入的攻击。长话短说,它曾经是针对编码不良的 Web 应用程序的常见攻击,并允许攻击者执行任意 SQL 命令。


0
投票
基本准备好的语句不易受到 SQL 注入的影响,并且查询响应时间更快。

我想你正在寻找这样的东西:

public static boolean isPersisted(Integer id) { String sql = "select id from table where id = ?"; PreparedStatement ps = con.prepareStatement(sql); ps.setInt(1, id);
    

0
投票

PreparedStatement

 已预编译。这意味着它们已被验证、转义和缓存(有关此问题中 
PreparedStatement
 预编译的更多详细信息
当我说准备好的语句已预编译时是什么意思?

预编译意味着所有工作只需完成一次,从而避免每次执行查询时执行此操作所需的所有成本。

但一如既往,如果使用得当,魔法就会实现。您可以使用

PreparedStatement

 连接创建一个 
String
,但要注意最终字符串中的任何更改都将导致新的预编译(从而失去好处)。

SQL 注入也是如此。始终使用占位符

?

。如果你在 
PreparedStatement
 中连接字符串(没有什么可以阻止你做这样的事情),你很容易陷入 SQL 注入,例如:

connection.prepareStatement("Select * from MY_TABLE where email = '" + userInputEmail + "'")

切勿执行上述操作。是一个 PreparedStatement

,但可以进行 SQL 注入。

因此,要从

PreparedStatements

中受益,请正确使用它们。

© www.soinside.com 2019 - 2024. All rights reserved.