ST_DWithin è stato più veloce nel mio test rispetto a ST_Intersects. Ciò è sorprendente, soprattutto perché si suppone che l'algoritmo della geometria preparata dia inizio a casi come questo. Penso che ci sia una possibilità che questo sarà molto più veloce di quello che ho mostrato qui.
Ho fatto qualche altro test e due cose hanno quasi raddoppiato la velocità. In primo luogo, ho provato su un computer più recente, ma ancora un laptop abbastanza ordinario, forse ad eccezione dei dischi sd3 SATA3.
Quindi la query seguente ha richiesto 18 secondi anziché 62 secondi sul vecchio laptop. Successivamente ho scoperto di aver sbagliato completamente prima quando ho scritto che l'indice sulla tabella dei punti non era necessario. Con questo indice in atto, ST_Intersects si è comportato come previsto e le cose sono diventate molto veloci. Ho aumentato il numero di punti nella tabella dei punti a 1 milione di punti e la query:
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);
dura 72 secondi. Poiché ci sono 1249 poligoni, i test 1249000000 vengono eseguiti in 72 secondi. Ciò rende circa 17000000 test al secondo. O testando quasi 14000 punti contro tutti i poligoni al secondo.
Da questo test i 400000000 punti da testare dovrebbero durare circa 8 ore senza problemi con la distribuzione del carico su più core. PostGIS non smette mai di impressionarmi :-)
Innanzitutto, per visualizzare il risultato è possibile aggiungere la geometria del punto alla tabella risultante, aprirla ad esempio in QGIS e modellarla con valori univoci nel campo Import_ct.
In secondo luogo, sì, puoi ottenere anche i punti che cadono fuori da qualsiasi poligono usando un join destro (o sinistro) in questo modo:
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);
Ho fatto alcuni test per verificare se PostGIS sembra possibile.
Prima cosa che non capisco. Hai due punti per riga. Entrambi i punti sono sempre nello stesso poligono? Quindi è sufficiente fare i calcoli su uno dei punti. Se possono trovarsi in due poligoni diversi, avrai bisogno di un modo per collegare una fila di punti a due poligoni.
Dai test sembra fattibile, ma potresti aver bisogno di una soluzione creativa per distribuire il carico su più di un CPU.
Ho testato su un laptop di 4 anni con CPU dual core centrino (credo a circa 2,2 GHz), 2 GB di RAM. Se hai 48 BG RAM, suppongo che tu abbia anche molta più potenza della CPU.
Quello che ho fatto è stato creare una tabella di punti casuale con 100000 punti come questo:
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;
Quindi aggiungendo un gid come:
ALTER TABLE t ADD COLUMN GID SERIAL;
Quindi in esecuzione:
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);
dura circa 62 secondi (confronta con il risultato ArcGIS con lo stesso numero di punti). Il risultato è una tabella che collega i punti nella mia tabella t con la gid nella tabella con tratto di censimento.
Con quella velocità otterrai circa 200 punti in circa 34 ore. Quindi, se è sufficiente verificare uno dei punti, il mio vecchio laptop può farlo con un core.
Ma se è necessario controllare entrambi i punti, potrebbe essere più difficile.
Quindi è possibile distribuire manualmente il carico su più core avviando più sessioni sul db ed eseguendo query diverse.
Nel mio esempio con 50000 punti e due CPU-core ho provato:
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);
su una sessione db contemporaneamente a esecuzione:
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);
in un'altra sessione db.
Ci sono voluti circa 36 secondi, quindi è un po 'più lento del primo esempio, probabilmente a seconda della scrittura del disco contemporaneamente. Ma dal momento che i core Bith funzionano contemporaneamente, non ci sono voluti più di 36 secondi del mio tempo.
Per unire le tabelle t1 e t2 a provato:
CREATE TABLE t3 AS
SELECT * FROM t1
UNION ALL
SELECT * FROM t2;
usando circa mezzo secondo.
Quindi, con hardware più fresco e distribuzione del carico su molti core, ciò dovrebbe essere assolutamente possibile anche se il mondo reale sarà più lento del test case.
Vale la pena notare che l'esempio è di Linux (Ubuntu). L'uso di Windows sarà un'altra storia. Ma ho tutte le altre applicazioni quotidiane in esecuzione, quindi il laptop è abbastanza carico da prima. Quindi questo potrebbe simulare il caso di Windows abbastanza bene forse, senza aprire altro che pgadmin.