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% です。

過去 1 か月以内にテーブルがバキューム処理されたため、このハード ドライブの使用率がわかりません。bool_valueには各行のレコードが既にあり、インデックスを削除しました。gis名前空間 (クエリで参照される)の両方のテーブルは、gidフィールドでインデックス化されます。これらのgis名前空間テーブルはビューではありません。これらは、PostGIS のPostGIS 2.0 Shapefile と DBF Loader Exporterを使用してインポートした SHP にすぎません。コンピューター上で他に重要なことは何も起きていません。

タスク マネージャーによると、postgres.exe プロセスであっても、CPU 使用率はほとんどありません。これは、極端なハード ドライブ アクティビティが原因であると考えられます。

パソコンは全部で8GB。その約半分は無料です。14 個の同時 postgres.exe プロセスが開いており、それぞれ 2.8 MB から 9 MB の容量があります。プロセスの 1 つだけが多くのアクティビティを示しています。

1 つ気になる点があります。2番目の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

それがうまくいった場合は、スライスを大きくして と を増やしLIMIT続けます。OFFSETパフォーマンスが良好である限り、スライスのサイズを増やします。必ず個別のトランザクションで実行してください。

これにより、キャッシングの問題 (過度のディスク負荷によって示される) を回避し、発生する可能性のある同時実行の問題も回避できます。いくつかの行の更新がまだ遅い場合は、間違いなく他の問題があります。


はどうかと言うと:

この 1 か月以内にテーブルがバキューム処理されたため、このハード ドライブの使用率がわかりません。

それは誤解です。通常は高速化されVACUUMませUPDATE(極端な場合のテーブル肥大を除く)。たぶんもっと遅い。でさらに悪いVACUUM FULL。これにより、無効なタプルがすべて削除され、データ ページが有効なタプルで可能な限り密にパックされます。

個々のデータ ページには「ゆらぎの余地」がないため、次の UPDATE ではHOT 更新を利用できません。更新が多い場合は、 の設定を低くすることを検討してfillfactorください。

dba.SE に関するこれらの密接に関連する質問の詳細とリンクについては、こちら、こちら、およびこちらご覧ください

于 2013-03-17T22:53:09.990 に答える