准备好的语句如何提高性能
How prepared statement improves performance
我看到下面的语句,它讲述了我们通过 JDBC PreparedStatement class.
获得的性能改进
If you submit a new, full SQL statement for every query or update to
the database, the database has to parse the SQL and for queries create
a query plan. By reusing an existing PreparedStatement you can reuse
both the SQL parsing and query plan for subsequent queries. This
speeds up query execution, by decreasing the parsing and query
planning overhead of each execution.
假设我正在创建语句并提供不同的值,而 运行 查询是这样的:
String sql = "update people set firstname=? , lastname=? where id=?";
PreparedStatement preparedStatement =
connection.prepareStatement(sql);
preparedStatement.setString(1, "Gary");
preparedStatement.setString(2, "Larson");
preparedStatement.setLong (3, 123);
int rowsAffected = preparedStatement.executeUpdate();
preparedStatement.setString(1, "Stan");
preparedStatement.setString(2, "Lee");
preparedStatement.setLong (3, 456);
int rowsAffected = preparedStatement.executeUpdate();
那么我是否仍会获得性能优势,因为我正在尝试设置不同的值,以便生成的最终查询根据值发生变化。
您能否准确解释一下我们何时获得性能优势?这些值也应该相同吗?
当你使用prepared statement(即预编译语句)时,DB一旦得到这条语句,它就会编译它并缓存它,以便它可以使用最后编译的语句来连续调用同一条语句。因此它会为连续调用进行预编译。
您通常使用带有绑定变量的准备语句,您在 运行 时提供变量。现在准备好的语句的连续执行会发生什么,您可以提供与先前调用不同的变量。从数据库的角度来看,它不必每次都编译语句,只需在朗姆酒时间插入绑定变量即可。所以变得更快。
预处理语句的其他优点是它可以防止SQL-注入攻击
因此值不必相同
虽然不是很明显 SQL 不是脚本而是一种 "compiled" 语言。这个汇编又名。优化又名硬解析是一项非常详尽的任务。 Oracle 有很多工作要做,它必须解析查询、解析 table 名称、验证访问权限、执行一些代数转换,然后它必须找到有效的执行计划。 Oracle(以及其他数据库)只能加入两个 tables - 不能更多。这意味着当您在 SQL 中加入多个 table 时,Oracle 必须将它们一个接一个地加入。也就是说,如果您在查询中加入 n
tables,则至少可以有 n!
个可能的执行计划。默认情况下,Oracle 在搜索 "optimal"(不是最好的一个)执行计划时被限制为最多 8000 个排列。
所以编译(硬解析)可能比查询执行本身更详尽。为了节省资源,Oracle 在称为库缓存的内存结构中共享会话之间的执行计划。这里可能会出现另一个问题,太多的解析需要对共享资源的独占访问。
因此,如果您进行过多(硬)解析,您的应用程序将无法扩展 - 会话会相互阻塞。
另一方面,有些情况下绑定变量没有帮助。
想象这样一个查询:
update people set firstname=? , lastname=? where group=? and deleted='N'
因为列 deleted
被索引并且 Oracle 知道有 98% 的值 ='Y' 而只有 2% 的值 = 'N' 它将推断使用和索引在 deleted
列中。如果您在 deleted
列上使用绑定变量作为条件,Oracle 无法找到有效的执行计划,因为它还依赖于编译时未知的输入。
(PS:从 11g 开始,绑定变量查看变得更加复杂)
我看到下面的语句,它讲述了我们通过 JDBC PreparedStatement class.
获得的性能改进If you submit a new, full SQL statement for every query or update to the database, the database has to parse the SQL and for queries create a query plan. By reusing an existing PreparedStatement you can reuse both the SQL parsing and query plan for subsequent queries. This speeds up query execution, by decreasing the parsing and query planning overhead of each execution.
假设我正在创建语句并提供不同的值,而 运行 查询是这样的:
String sql = "update people set firstname=? , lastname=? where id=?";
PreparedStatement preparedStatement =
connection.prepareStatement(sql);
preparedStatement.setString(1, "Gary");
preparedStatement.setString(2, "Larson");
preparedStatement.setLong (3, 123);
int rowsAffected = preparedStatement.executeUpdate();
preparedStatement.setString(1, "Stan");
preparedStatement.setString(2, "Lee");
preparedStatement.setLong (3, 456);
int rowsAffected = preparedStatement.executeUpdate();
那么我是否仍会获得性能优势,因为我正在尝试设置不同的值,以便生成的最终查询根据值发生变化。
您能否准确解释一下我们何时获得性能优势?这些值也应该相同吗?
当你使用prepared statement(即预编译语句)时,DB一旦得到这条语句,它就会编译它并缓存它,以便它可以使用最后编译的语句来连续调用同一条语句。因此它会为连续调用进行预编译。
您通常使用带有绑定变量的准备语句,您在 运行 时提供变量。现在准备好的语句的连续执行会发生什么,您可以提供与先前调用不同的变量。从数据库的角度来看,它不必每次都编译语句,只需在朗姆酒时间插入绑定变量即可。所以变得更快。
预处理语句的其他优点是它可以防止SQL-注入攻击
因此值不必相同
虽然不是很明显 SQL 不是脚本而是一种 "compiled" 语言。这个汇编又名。优化又名硬解析是一项非常详尽的任务。 Oracle 有很多工作要做,它必须解析查询、解析 table 名称、验证访问权限、执行一些代数转换,然后它必须找到有效的执行计划。 Oracle(以及其他数据库)只能加入两个 tables - 不能更多。这意味着当您在 SQL 中加入多个 table 时,Oracle 必须将它们一个接一个地加入。也就是说,如果您在查询中加入 n
tables,则至少可以有 n!
个可能的执行计划。默认情况下,Oracle 在搜索 "optimal"(不是最好的一个)执行计划时被限制为最多 8000 个排列。
所以编译(硬解析)可能比查询执行本身更详尽。为了节省资源,Oracle 在称为库缓存的内存结构中共享会话之间的执行计划。这里可能会出现另一个问题,太多的解析需要对共享资源的独占访问。 因此,如果您进行过多(硬)解析,您的应用程序将无法扩展 - 会话会相互阻塞。
另一方面,有些情况下绑定变量没有帮助。 想象这样一个查询:
update people set firstname=? , lastname=? where group=? and deleted='N'
因为列 deleted
被索引并且 Oracle 知道有 98% 的值 ='Y' 而只有 2% 的值 = 'N' 它将推断使用和索引在 deleted
列中。如果您在 deleted
列上使用绑定变量作为条件,Oracle 无法找到有效的执行计划,因为它还依赖于编译时未知的输入。
(PS:从 11g 开始,绑定变量查看变得更加复杂)