【问题标题】:Why PreparedStatement is much faster than Statement?为什么 PreparedStatement 比 Statement 快得多?
【发布时间】:2015-02-09 00:44:23
【问题描述】:

几天前,我不得不使用内存计算框架创建一些处理性能测试。因此,为了做到这一点,我需要一个大数据池,并根据各种性能测试逐步增加。

数据库是 Oracle,包含 22 个字段的表。该表需要从 100 万条记录逐渐填充到 1 亿条记录。

为了用 1 百万填充表,我生成了随机测试数据并使用 java 语句将其插入数据库,这大约花费了 17 和 16 秒分。在那之后,我很快意识到填充 1 亿条记录表需要很长时间,所以我用 PreparedStatement 进行了尝试,因为我知道这样会快一点……但差别太大了,1 分 24 秒,我已经开始在网上搜索这背后的原因,并找到了一些原因,但在我看来,没有任何原因会产生这种影响。

这就是我发现的可以解释这种差异的原因: LINK

PreparedStatement 被预编译 在数据库中,访问计划也缓存在数据库中,这允许数据库执行使用准备好的语句编写的参数查询比普通查询快得多,因为它要做的工作更少。您应该始终尝试在生产 JDBC 代码中使用 PreparedStatement 来减少数据库负载。为了获得性能优势,值得注意的是只使用参数化版本的 sql 查询,而不是字符串连接。

但是 所有数据都是随机生成的,因此不应该涉及来自 oracle 端的主要缓存。

【问题讨论】:

  • 阅读有关 Oracle 硬解析和软解析以及 SGA 的信息。用于硬解析的未准备/文字版本的插入有很多处理周期。
  • 我建议您在进行此类更改之前和之后跟踪程序。确保测试公平。然后分析生成的跟踪文件。结果往往令人惊讶。

标签: java oracle jdbc


【解决方案1】:

Oracle 可能能够在语句缓存中缓存查询计划;根据 Oracle® 数据库 JDBC 开发人员指南Implicit Statement Caching

启用隐式 Statement 缓存后,当您调用该语句对象的 close 方法时,JDBC 会自动缓存准备好的或可调用的语句。使用标准连接对象和语句对象方法缓存和检索准备好的和可调用的语句。

普通语句不会被隐式缓存,因为隐式语句缓存使用 SQL 字符串作为键,而普通语句是在没有 SQL 字符串的情况下创建的。因此,隐式 Statement 缓存仅适用于使用 SQL 字符串创建的 OraclePreparedStatementOracleCallableStatement 对象。

【讨论】:

  • 好的,可以说查询计划被缓存了,但我仍然有 22 个随机字段每个插入,这是总插入语句的一半以上...
  • 但是您没有发送整个查询;只是一个查询 ID(和您的字段)。不是查询 plus 字段。然后添加缓存。
  • 我看不到 PreparedStatement 的关闭位置。我当然明白,如果有人用相同的 SQL 关闭和重新打开准备好的语句,隐式缓存会有多大帮助,但是问题中的 PreparedStatement 示例在我看来就像准备好的语句的标准实现(发送语句一次,然后发送每个查询的参数)。我错过了什么吗?
  • @aurelianus 查询计划不是查询的文本,它大致类似于查询的字节码。重复使用该计划无需编译一百万行代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-10-24
  • 2014-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-10
  • 2011-06-18
相关资源
最近更新 更多