可以编写SQL语句来重写数据库吗?

时间:2015-02-04 15:20:48

标签: java sql postgresql jdbc

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

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

在PostgreSQL上运行时,我注意到实际运行的查询(在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)

重写的查询几乎无限量地运行,而非重写的查询在几分钟内完成,如果不是几秒钟。

问题:

  • 数据库(我推测)是否通常重写查询?
  • 如果是的话,为什么PostgreSQL愚蠢到足以让自己陷入困境?这是一个已知的错误吗?
  • 如何避免查询重写 - 在数据库但最好是JDBC级别?

2 个答案:

答案 0 :(得分:1)

认为这与原始查询

的事实有某种关系
UPDATE table_name SET column2 = column1

没有WHERE声明。

我将查询更改为

UPDATE table_name SET column2 = column1 WHERE 1=1

,它只是按照我期望的方式工作。

很抱歉这不是科学/参考解释,但希望这对某些人来说仍然有用。我之前使用过这个技巧用于不同的目的(一些遗留数据库需要WHERE子句),它似乎也为这个案例做了工作。

答案 1 :(得分:-3)

有些数据库实际上是重写代码(虽然不是数据库可以做到这一点,但java - java知道如何在有有效连接后转换代码),但是你的查询是误导Postgres。 Postgres完全按照您的要求执行,因为该查询实际上应该影响数据库中的所有行。但如果您的计划不同,那么您应该告诉我们您的目标是什么