我有这个相当无辜的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)
重写的查询几乎无限量地运行,而非重写的查询在几分钟内完成,如果不是几秒钟。
问题:
答案 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完全按照您的要求执行,因为该查询实际上应该影响数据库中的所有行。但如果您的计划不同,那么您应该告诉我们您的目标是什么