私のテストでは、ST_DWithinはST_Intersectsよりも高速でした。特に、準備されたジオメトリアルゴリズムがこのような場合に作動することになっているため、これは驚くべきことです。ここで示したよりもかなり高速になる可能性があると思います。
さらにテストを行ったところ、2つのことが速度をほぼ10倍にしました。最初に、新しいコンピューターで試しましたが、SATA3 ssd -disksを除いて、かなり普通のラップトップでした。
次に、古いラップトップでは62秒ではなく18秒かかりました。次に、ポイントテーブルのインデックスは不要であると書いたとき、私はまったく間違っていたことがわかりました。そのインデックスを配置すると、ST_Intersectsは期待どおりに動作し、非常に高速になりました。ポイントテーブルのポイント数を100万ポイントとクエリに増やしました。
CREATE TABLE points_ct AS
SELECT imported_ct.gid as ct_gid, t.gid as point_id
FROM imported_ct , t WHERE ST_Intersects(imported_ct.geom , t.geom);
72秒で実行されます。1249個のポリゴンがあるため、1249000000テストは72秒で完了します。これは、1秒あたり約17000000テストになります。または、毎秒すべてのポリゴンに対してほぼ14000ポイントをテストします。
このテストから、テストする400000000ポイントは、負荷を複数のコアに分散する際に問題なく約8時間かかります。PostGISが私を感動させることは決してありません:-)
まず、結果を視覚化するために、結果のテーブルにポイントジオメトリを追加し、たとえばQGISで開いて、imported_ctフィールドの一意の値でスタイルを設定できます。
第二に、はい、次のように右(または左)結合を使用して、ポリゴンの外側にあるポイントを取得することもできます。
CREATE TABLE points_ct AS
SELECT imported_ct.gid as ct_gid, t.gid as point_id
FROM imported_ct right join t ON ST_Intersects(imported_ct.the_geom , t.geom);
PostGISが可能かどうかを確認するために、いくつかのテストを行いました。
最初に私が理解できないこと。行ごとに2つのポイントがあります。常に両方のポイントが同じポリゴンにありますか?次に、いずれかのポイントで計算を行うだけで十分です。2つの異なるポリゴンに配置できる場合は、1つのポイント行を2つのポリゴンに接続する方法が必要です。
テストからは実行可能と思われますが、負荷を複数のCPUコアに分散させるための創造的なソリューションが必要になる場合があります。
デュアルコアのCentrino CPU(約2.2 GHzと思う)、2 GB RAMを搭載した4歳のラップトップでテストしました。48個のBG RAMがある場合は、CPUパワーもはるかに大きいと思います。
私がしたことは、次のように100000ポイントのランダムポイントテーブルを作成することでした。
CREATE TABLE t AS
WITH r AS
(SELECT ST_Extent(the_geom)::geometry ext FROM imported_ct)
SELECT ST_Point(x,y) AS geom FROM
(SELECT GENERATE_SERIES(1,100000)) s,
(SELECT ST_Xmin(ext)+(random()*(ST_Xmax(ext)-ST_Xmin(ext))) x, ST_Ymin(ext)+(random()*(ST_Ymax(ext)-ST_Ymin(ext))) y FROM r
) f;
次に、次のようなgidを追加します。
ALTER TABLE t ADD COLUMN GID SERIAL;
次に実行します:
CREATE TABLE points_ct AS
SELECT imported_ct.gid as ct_gid, t.gid as point_id FROM imported_ct , t WHERE ST_Dwithin(imported_ct.the_geom , t.geom,0);
約62秒かかります(同じポイント数でのArcGISの結果と比較してください)。結果は、テーブルtのポイントと国勢調査地区のテーブルのgidを接続するテーブルです。
その速度で、約34時間で200ミルポイントを処理できます。したがって、ポイントの1つをチェックするだけで十分であれば、私の古いラップトップは1つのコアでそれを行うことができます。
ただし、両方のポイントを確認する必要がある場合は、難しいかもしれません。
その後、dbに対して複数のセッションを開始して異なるクエリを実行することにより、手動で負荷を複数のコアに分散できます。
私の例では、50000ポイントと2つのCPUコアを試しました。
CREATE TABLE t1 as
SELECT imported_ct.gid as ct_gid, t.gid as point_id FROM imported_ct , t WHERE t.gid >50000 and ST_Dwithin(imported_ct.the_geom , t.geom,0);
実行と同時に1つのdbセッションで:
CREATE TABLE t2 as
SELECT imported_ct.gid as ct_gid, t.gid as point_id FROM imported_ct , t WHERE t.gid <=50000 and ST_Dwithin(imported_ct.the_geom , t.geom,0);
別のdbセッションで。
それには約36秒かかりましたので、おそらく同時にディスクの書き込みに依存している最初の例よりも少し遅くなります。しかし、bithコアは同時に動作しているため、36秒以上かかることはありませんでした。
テーブルt1とt2を結合するには
CREATE TABLE t3 AS
SELECT * FROM t1
UNION ALL
SELECT * FROM t2;
約0.5秒使用します。
したがって、新しいハードウェアを使用し、多くのコアに負荷を分散することにより、実際の環境がテストケースよりも遅くなる場合でも、これは絶対に可能になります。
この例はLinux(Ubuntu)からのものであることに注意してください。Windowsの使用もまた別の話です。しかし、私は他のすべての日常的なアプリケーションを実行しているので、ラップトップは以前からかなり負荷がかかっています。したがって、pgadmin以外を開かずに、Windowsの場合を非常にうまくシミュレートできます。