0

我有一张有 370 万行的表。它有一个布尔值(下面称为bool_value),它已经为所有行提供了一个值。

我正在使用此查询来更新bool_value

DROP INDEX IF EXISTS table_bool_value_idx;

UPDATE table
SET bool_value = (
st_contains(st_setsrid((SELECT geom FROM gis.cntys04_3081 WHERE gid=57), 3081), the_geom)
AND st_contains((SELECT geom_3081 FROM gis.stratmap_city_poly_v4 WHERE gid = 127), the_geom)
);

到目前为止,此查询已经运行了大约 12 个小时。一直以来,我的硬盘驱动器的利用率都是 100%。

我不明白这个硬盘利用率,因为该表在过去一个月内已被清理,bool_value已经有每一行的记录,我删除了索引。gis命名空间中的两个表(在查询中引用)都在它们的gid字段上建立索引。那些gis命名空间表不是视图。它们只是我使用 PostGIS 的PostGIS 2.0 Shapefile 和 DBF Loader Exporter导入的 SHP 。计算机上没有其他重要的事情发生。

根据任务管理器,CPU 利用率几乎为零,即使在 postgres.exe 进程上也是如此。我认为这是由于极端的硬盘活动造成的。

计算机总共有 8GB。其中几乎一半是免费的。有 14 个并发 postgres.exe 进程打开,每个进程的大小在 2.8 MB 到 9 MB 之间。只有一个过程显示出大量活动。

这是我想知道的一件事:第二个 st_contains 中的geom_3081长度为 1.0 MB。这是一个代表德克萨斯州达拉斯市范围的 PostGIS MULTIPOLYGON。我想如果没有别的,这将被 Windows 磁盘缓存缓存,以防止重复的硬盘访问。geom_3081没有被索引,虽然我不明白为什么索引它会有所帮助,因为它没有被用来确定要返回哪些行;gid领域正在这样做。

4

1 回答 1

1

无论这里存在什么其他问题(很可能还有其他问题),这应该会使您的查询更快:

UPDATE table t
SET    bool_value = x.new_bool
FROM (
   SELECT table_id
         ,(st_contains(st_setsrid
               ((SELECT geom FROM gis.cntys04_3081 WHERE gid=57)
                 ,3081
               ), the_geom)
           AND st_contains
              ((SELECT geom_3081 FROM gis.stratmap_city_poly_v4 WHERE gid = 127)
              ,the_geom
              )
          ) AS new_bool
   FROM   table
   ) upd
WHERE  t.table_id = upd.table_id
AND    t.bool_value IS DISTINCT FROM x.new_bool;

table_id是这里的主键。

原则是避免空更新。而且由于我们谈论的是布尔值,很可能,您有很大一部分更新实际上并没有改变任何东西。但是这样的更新仍然会导致磁盘活动,因为旧行被标记为过时并且插入了新的(未更改的)行。

要找出还有什么问题,您可以走行之有效的分而治之之路:附加到子查询:

ORDER  BY table_id
LIMIT  10
OFFEST 0

如果通过,继续增加LIMITOFFSET,使用更大的切片。只要性能保持良好,就增加切片的大小。确保在不同的事务中运行。

这可以避免缓存问题(如磁盘负载过大所表明的那样),也可以避免您可能遇到的任何并发问题。如果更新几行仍然很慢,那么您肯定还有其他问题。


至于:

我不明白这个硬盘驱动器的使用情况,因为该表在过去一个月内已被清空,

这是一种误解。VACUUM通常不会变得更快(表膨胀的极端情况UPDATE除外)。甚至可能更慢。更糟糕的是VACUUM FULL。这将删除所有死元组并尽可能紧密地用活动元组打包数据页。

以下更新不能使用HOT 更新,因为在个人数据页面上没有“回旋余地”。如果您有很多更新,请考虑将fillfactor.

在这些与 dba.SE 密切相关的问题中可以找到更多信息和链接,请点击此处此处此处

于 2013-03-17T22:53:09.990 回答