Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/78.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
提高表中SQL更新的性能_Sql_Postgresql_Postgresql 9.3 - Fatal编程技术网

提高表中SQL更新的性能

提高表中SQL更新的性能,sql,postgresql,postgresql-9.3,Sql,Postgresql,Postgresql 9.3,我正在运行一个如下的查询 update foo f set type=b.type from bar b where f.bar_id = b.id; 每个表都有几百万行。我觉得奇怪的是,对这个查询进行分析后发现它运行了两次表扫描,而不是使用它在bars主键上连接的事实 有没有想过如何使用索引或以其他方式提高速度?PostgreSQL在计算此类语句的成本方面做得很差。问题在于,它的成本相当于它只是一个选择查询,忽略了这样一个事实,即它现在必须访问foo的每个符合条件的行才能对其进行更改。因此,

我正在运行一个如下的查询

update foo f set type=b.type from bar b where f.bar_id = b.id;
每个表都有几百万行。我觉得奇怪的是,对这个查询进行分析后发现它运行了两次表扫描,而不是使用它在
bar
s主键上连接的事实


有没有想过如何使用索引或以其他方式提高速度?

PostgreSQL在计算此类语句的成本方面做得很差。问题在于,它的成本相当于它只是一个选择查询,忽略了这样一个事实,即它现在必须访问
foo
的每个符合条件的行才能对其进行更改。因此,如果它选择了一个查询路径,该路径返回的
foo
行不符合物理顺序,这几乎是除以下路径之外的所有查询路径:

nested loop
    seq scan on foo
    index scan on bar
然后,它会跳到整个国家,试图更新出顺序的
foo

如果它确实选择了上面的计划,那么现在它正在跳过
读取顺序。但是在弄脏的页面上跳来跳去通常比在没有弄脏的情况下在阅读页面上跳来跳去要糟糕得多

您最好的选择可能是使用CREATE TABLE重新创建
foo2
,如SELECT。。。 然后重新命名。如果存在大量外键约束和引用
foo
的视图,这可能会很痛苦

如果您有RAM,您可以尝试启动work_mem,以获得单通计划:

hash join
    seq scan on foo
    hash
        seq scan on bar
但如果它决定需要多次传球,因为它不适合记忆,那么事情就会急转直下,因为你又回到了随机跳跃的状态。更糟糕的是,PostgreSQL在计划这方面毫无帮助,而且您也很可能会

hash join
    seq scan on bar
    hash
        seq scan on foo

这是一个可怕的计划。

在您的案例中考虑事务日志压力。您是否可以将事务拆分为多个事务,每个事务中有5万行


另外,如果更新>1m行,我建议您在更新之前将除covers WHERE子句之外的所有索引更改为非活动状态

foo
中,有多少记录将更新为所有记录的百分比?这次更新将使用多少条bar记录?所有记录都在foo中更新(实际上是数据非规范化后的回填)。两个表中都有几百万行。特别是在这个模式中,条形图实际上拥有foo,所以所有的条形图都可能会被使用。那么,为什么你认为完全读取不是这个操作的最佳方式呢?只是看起来它比应该的慢得多。几个小时没有结果。(机器上的所有统计数据[cpu、mem、磁盘i/o]似乎都正常)在
foo
上使用索引只需要更多的i/o,在这种情况下没有任何好处,因为您正在读取整个表。它可能对
条码有用,但取决于。。。嗯,各种各样的事情。请显示实际的
解释
输出,不要只是描述它。如果您对公开表名感到偏执,请使用的“匿名化计划”选项。您所说的“事务日志压力”到底是什么意思?Postgres不使用术语“事务日志”。非常长的事务会在tran.log中急剧增长。这意味着在发生提交/回滚时会发生大量I/O。如果你把交易分成几个小部分,你就能及时获胜。你知道Postgres没有一个叫做“交易日志”的东西可以“填满”吗?对于SQL Server,您的说法可能是正确的,但对于许多其他DBMS(包括Postgres和Oracle),执行较少的大型事务几乎总是比执行许多小型事务更快。您完全正确。对不起,我在回答时考虑了MSSQL,对不起。标记“sql”对我来说似乎是一个不为人知的错误:)与MS sql Server相关的问题(应该)标记为
sql Server