prepared SQL语句可以被数据库改写吗?

Can prepared SQL statement be rewritten by the database?

我有这个看起来相当无辜的 JDBC 代码:

String sql = "UPDATE table_name SET column2 = column1";
try (PreparedStatement statement = dbConnection.prepareStatement(sql)) {
  statement.executeUpdate();
}
dbConnection.commit();

当在 PostgreSQL 上 运行ning 时,我注意到 实际 运行ning 查询(从 PostgreSQL 中可见)如下:

UPDATE table_name SET column2 = i.column1 FROM table_name i

问题是重写的查询 更昂贵:

# explain update table_name set column2 = i.column1 from table_name i;

                         QUERY PLAN                                      

-------------------------------------------------------------------------------  
Update on table_name  (cost=0.00..3586127424.55 rows=206294914809 width=166)          
   ->  Nested Loop  (cost=0.00..3586127424.55 rows=206294914809 width=166)
         ->  Seq Scan on table_name (cost=0.00..15453.97 rows=454197 width=156)
         ->  Materialize  (cost=0.00..19942.96 rows=454197 width=10)
               ->  Seq Scan on table_name i  (cost=0.00..15453.97 rows=454197 width=10)

(5 rows)

而不是

# explain update table_name set column2 = column1;

                           QUERY PLAN                                

------------------------------------------------------------------------
Update on table_name  (cost=0.00..15453.97 rows=454197 width=156)
 ->  Seq Scan on table_name  (cost=0.00..15453.97 rows=454197 width=156)
(2 rows)

重写的查询花费了几乎无限的时间 运行 而非重写的查询在几分钟甚至几秒钟内完成。

问题:

有些数据库实际上会重写代码(尽管这不是数据库起作用,而是 java -- java 了解如何在建立有效连接后转换代码)但是您的query 是误导 Postgres 的东西。 Postgres 完全按照您的要求执行,因为该查询实际上应该影响数据库中的所有行。但如果您的计划有所不同,那么您应该让我们知道您的目标是什么

认为 这在某种程度上与原始查询

UPDATE table_name SET column2 = column1

没有WHERE声明。

一旦我将查询更改为

UPDATE table_name SET column2 = column1 WHERE 1=1

,它就像我期望的那样工作。

抱歉,这不是 scientific/referenced 解释,但希望这仍然对某些人有所帮助。我之前出于不同的目的使用过这个技巧(一些遗留数据库需要 WHERE 子句)并且它似乎也适用于这种情况。