Ottimizzazione di un punto molto ampio nella query poligonale


9

Ho un set di dati nazionale di punti di indirizzo (37 milioni) e un set di dati poligonale di contorni di inondazioni (2 milioni) di tipo MultiPolygonZ, alcuni dei poligoni sono molto complessi, il numero massimo di ST_NPoints è di circa 200.000. Sto cercando di identificare con PostGIS (2.18) quali punti di indirizzo si trovano in un poligono di inondazione e scriverli in una nuova tabella con ID indirizzo e dettagli sul rischio di alluvione. Ho provato dal punto di vista dell'indirizzo (ST_Within) ma poi l'ho scambiato partendo dal punto di vista dell'area di alluvione (ST_Contains), in base alla logica che ci sono ampie aree senza alcun rischio di alluvione. Entrambi i set di dati sono stati riproiettati in 4326 ed entrambe le tabelle hanno un indice spaziale. La mia query qui sotto è in corso da 3 giorni e non mostra alcun segno di finire presto!

select a.id, f.risk_factor_1, f.risk_factor_2, f.risk_factor_3
into gb.addresses_with_flood_risk
from gb.flood_risk_areas f, gb.addresses a
where ST_Contains(f.the_geom, a.the_geom);

C'è un modo più ottimale per eseguire questo? Inoltre, per query a lungo termine di questo tipo, qual è il modo migliore per monitorare i progressi oltre a guardare l'utilizzo delle risorse e pg_stat_activity?


La mia query originale è andata a buon fine, anche se per 3 giorni e mi sono allontanato da altri lavori, quindi non ho mai avuto il tempo di provare la soluzione. Tuttavia, ho appena visitato nuovamente questo sito e ho esaminato le raccomandazioni, finora tutto bene. Ho usato il seguente:

  1. Creato una griglia di 50 km nel Regno Unito usando la soluzione ST_FishNet suggerita qui
  2. Imposta l'SRID della griglia generata su British National Grid e crea un indice spaziale su di essa
  3. Ho salvato i miei dati di flood (MultiPolygon) usando ST_Intersection e ST_Intersects (solo qui ho dovuto usare ST_Force_2D sul geom dato che shape2pgsql ha aggiunto un indice Z
  4. Ho registrato i miei dati dei punti usando la stessa griglia
  5. Indici creati sulla riga e col e indice spaziale su ciascuna delle tabelle

Sono pronto per eseguire la mia sceneggiatura ora, passerò in rassegna le righe e le colonne popolando i risultati in una nuova tabella fino a quando non avrò coperto l'intero paese. Ma ho appena controllato i miei dati di alluvione e alcuni dei più grandi poligoni sembrano essersi persi nella traduzione! Questa è la mia domanda:

SELECT g.row, g.col, f.gid, f.objectid, f.prob_4band, ST_Intersection(ST_Force_2D(f.geom), g.geom) AS geom 
INTO rofrse.tmp_flood_risk_grid 
FROM rofrse.raw_flood_risk f, rofrse.gb_grid g
WHERE (ST_Intersects(ST_Force_2D(f.geom), g.geom));

I miei dati originali si presentano così:

Dati di alluvione originali

Comunque dopo il ritaglio sembra così:

Dati di inondazione con griglia

Questo è un esempio di un poligono "mancante":

Poligono "mancante"


Mi sono appena reso conto che ci siamo incontrati al FOSS4G di Seoul e abbiamo parlato delle meraviglie dell'hub di localizzazione ESRI :-)
John Powell

Hai mai finito l'approccio di divisione e conquista? Puoi aggiornare i tempi di riferimento con questo approccio?
Andrew,

Risposte:


6

Per rispondere prima alla tua ultima domanda, vedi questo postsull'opportunità di essere in grado di monitorare l'avanzamento delle query. Il problema è difficile e verrebbe aggravato da una query spaziale, poiché sapere che il 99% degli indirizzi era già stato scansionato per il contenimento in un poligono flood, che si potrebbe ottenere dal contatore di loop nell'implementazione della scansione della tabella sottostante, non necessariamente aiutare se l'ultimo 1% di indirizzi interseca un poligono di alluvione con il maggior numero di punti, mentre il precedente 99% interseca una piccola area. Questo è uno dei motivi per cui EXPLAIN a volte può essere inutile con lo spazio, in quanto fornisce un'indicazione delle righe che verranno scansionate, ma, per ovvie ragioni, non tiene conto della complessità dei poligoni (e quindi di una grande proporzione del tempo di esecuzione) di tutte le query sul tipo di intersezione / intersezione.

Un secondo problema è che se guardi qualcosa del genere

EXPLAIN 
SELECT COUNT(a.id) 
FROM sometable a, someothertable b
WHERE ST_Intersects (a.geom, b.geom)

vedrai qualcosa di simile, dopo aver perso molti dettagli:

_st_intersects(a.geom, b.geom)
   ->  Bitmap Index Scan on ix_spatial_index_name  (cost...rows...width...))
   Index Cond: (a.geom && geom)

La condizione finale, &&, significa fare un check box di delimitazione, prima di fare qualsiasi intersezione più accurata delle geometrie effettive. Questo è ovviamente sensato e alla base di come funzionano gli R-Trees. Tuttavia, in passato ho lavorato anche ai dati sulle alluvioni del Regno Unito, quindi ho familiarità con la struttura dei dati, se i (multi) poligoni sono molto estesi - questo problema è particolarmente acuto se un fiume scorre, diciamo, 45 gradi - ottieni enormi riquadri di delimitazione, che potrebbero forzare un numero enorme di potenziali intersezioni da controllare su poligoni molto complessi.

L'unica soluzione che sono stato in grado di trovare per il problema "la mia query è in esecuzione da 3 giorni e non so se siamo al 1% o al 99%" è usare una specie di divisione e conquista per i manichini Approccio, intendo dire, suddividere la propria area in blocchi più piccoli ed eseguirli separatamente, in un ciclo in plpgsql o esplicitamente nella console. Questo ha il vantaggio di tagliare poligoni complessi in parti, il che significa che i punti successivi nei controlli poligonali stanno lavorando su poligoni più piccoli e le scatole di delimitazione dei poligoni sono molto più piccole.

Sono riuscito a eseguire query in un giorno dividendo il Regno Unito in blocchi di 50 km per 50 km, dopo aver ucciso una query che era in corso da oltre una settimana in tutto il Regno Unito. A parte questo, spero che la tua domanda sopra sia CREATE TABLE o UPDATE e non solo un SELECT. Quando aggiorni una tabella, gli indirizzi, in base al fatto di trovarsi in un poligono flood, dovrai comunque scansionare l'intera tabella in fase di aggiornamento, indirizzandoli, quindi avere effettivamente un indice spaziale su di essa non è di alcun aiuto.

EDIT: Sulla base del fatto che un'immagine vale più di mille parole, ecco un'immagine di alcuni dati di alluvione del Regno Unito. Esiste un multipoligono molto grande, il cui riquadro di selezione copre l'intera area, quindi è facile vedere come, ad esempio, intersecando prima il poligono di alluvione con la griglia rossa, il quadrato nell'angolo sud-ovest verrebbe improvvisamente testato contro un piccolo sottoinsieme del poligono.

inserisci qui la descrizione dell'immagine


Ciao John e grazie mille per la risposta esaustiva, seguirò la tua raccomandazione sull'approccio alla griglia, sembra un suggerimento molto sensato, non voglio davvero semplificare e perdere precisione. Farò un benchmark con un blocco e poi correrò in parallelo, molto più facile in questi giorni con il cloud! Grazie ancora
Mark Varley

Ciao Mark, non preoccuparti, considera di accettare la risposta se ritieni che abbia aiutato. Aiuta a mantenere pulito il sito, le domande senza risposte accettate sono una delle metriche che vengono esaminate dai siti di scambio di stack.
John Powell,

OK tutto fatto, questo è il mio primo post qui, di solito trovo la risposta dai thread dettagliati e risposte utili. La query è finalmente terminata stamattina dopo circa 3 giorni, il che non è male, ma seguirà i tuoi consigli oggi e li dividerà in pezzi per una migliore performance. Grazie ancora per il tuo aiuto John e forse ci vediamo a Bonn ad agosto!
Mark Varley,

Ho aggiunto una foto, anche se mi rendo conto che hai l'immagine: D, potrebbe aiutare gli altri a visualizzare ciò di cui mi occupo. Sì, quasi sicuramente andrò nel Foss4G UK e penserò a Bonn.
John Powell,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.