当它们包含 ROW_NUMBER() 时,JDBC-driver / SQL Server 总是重新编译我准备好的语句

Posted

技术标签:

【中文标题】当它们包含 ROW_NUMBER() 时,JDBC-driver / SQL Server 总是重新编译我准备好的语句【英文标题】:JDBC-driver / SQL Server recompiles my prepared statements all the time when they contain ROW_NUMBER() 【发布时间】:2009-09-17 13:23:27 【问题描述】:

我注意到包含 ROW_NUMER() 代码的准备好的语句经常被重新编译,尽管它们的 SQL 代码没有改变。

(Inside Microsoft SQL Server 2008: T-SQL Querying 一书中的示例):

WITH SalesRN AS (
 SELECT
  ROW_NUMBER() OVER (ORDER BY qty, empid) AS rownum,
  empid,
  mgrid,
  qty
 FROM
  dbo.SalesOrder
)
SELECT 
 rownum,
 empid,
 mgrid,
 qty
FROM
 SalesRN
WHERE
 rownum > 100 * (?-1)
 AND rownum <= 100 * ?
ORDER BY
 rownum

我正在使用最新版本的 jTDS JDBC 驱动程序 (1.2.3),并注意到 SQL Server 2005 和 2008 都存在问题。

有人知道发生了什么吗?为什么它会重新编译语句,尽管它们的代码没有改变?对于我的一个查询,重新编译大约需要 1200 毫秒,与低至 31 毫秒的执行时间相比,这是很多。

【问题讨论】:

【参考方案1】:

我怀疑它被重新编译以优化分页,因为这个位:

rownum > 100 * (?-1)
 AND rownum <= 100 * ?

不过,我也符合 SalesRN 的条件 (dbo.SalesRN)。这也可能是原因。

最后,您可以使用query hint。这是一门黑色艺术。我会从 KEEP PLAN 或 OPTIMIZE FOR UNKNOWN 开始。

【讨论】:

听起来很可能,这取决于 SalesRN 中的行数和 rownum 的整体分布。 但是决定何时重新编译语句的不是 JDBC 驱动程序,而不是 SQL Server? 不,SQL Server 优化器。 JDBC如何重新编译它?它可以准备不同的语句

以上是关于当它们包含 ROW_NUMBER() 时,JDBC-driver / SQL Server 总是重新编译我准备好的语句的主要内容,如果未能解决你的问题,请参考以下文章

在运行 spark 应用程序时包含 aws jdbc 驱动程序

ROW_NUMBER() 替代

SQL+获取具有最新日期的行+row_number()+重复时的情况

SpringBoot 数据篇之使用JDBC

oracle 分析函数2

数据库分析函数 ROW_NUMBER() rank() dense_rank() 的区别