Indice spaziale PostgreSQL / PostGIS - nessuna accelerazione


15

Ho una tabella spaziale in un database PostgreSQL / PostGIS. Ogni riga in esso rappresenta un poligono. È della seguente forma:

+----+--------+
|gid |   way  |
+----+--------+
|241 | 01030..|

La colonna geometrica è "way" che contiene la geometria di un poligono. In WKT è: POLYGON (('....')). Sto eseguendo molte query ST_Contains su questa tabella, per verificare se due poligoni sono contenuti l'uno nell'altro, ad esempio:

Select ST_Contains(a.way, b.way) From table AS a, table AS b Where a.gid = 15 And b.gid = 16

Mi chiedevo come velocizzare questa query e ho aggiunto un indice spaziale sul tavolo:

CREATE INDEX table_way_gist ON table USING gist(way);

Ma in realtà non vedo una velocità. Creo l'indice DOPO aver riempito la tabella con tutti i poligoni PRIMA di eseguire le query ST_Contains. L'indice deve essere aggiunto prima di riempire una tabella? Esistono requisiti speciali sulla tabella per lavorare con l'indice? La proiezione (srid) della via della colonna geometrica è impostata su 900913.

Sto usando: psql (PostgreSQL) 9.1.4 / POSTGIS = "1.5.3"

Risposte:


16

L'indice più efficiente per la query espressa nella tua domanda è quello su gid in quanto è l'unica colonna che appare in un'espressione dove:

 CREATE INDEX table_gid ON table (gid);

È possibile eliminare in modo sicuro l'indice gist poiché consumerà solo spazio e rallenterà gli inserimenti / aggiornamenti / eliminazioni.

Lunga spiegazione

Come ho detto, l'indice più efficace nel tuo caso è quello su gid in quanto consentirà al motore db di recuperare le righe più velocemente (con il recupero che di solito è la parte più lenta del processo). Dopodiché probabilmente calcolerà meglio il risultato di

  ST_Contains(a.way, b.way)

espressione senza guardare l'indice. Il motivo è che il pianificatore di query stimerà probabilmente che il costo aggiuntivo della ricerca dell'indice gist su entrambe le colonne rispetto alla ricerca diretta dei valori a.way e b.way non vale la pena in quanto il numero totale di righe da cercare è probabilmente molto piccolo, specialmente se l'indice è unico.

Come regola generale, ricorda che il pianificatore probabilmente favorirà una scansione della tabella rispetto a una scansione dell'indice per piccoli set di dati (le dimensioni del set di dati sono stimate guardando le statistiche della tabella).


Questo mi rende più chiaro il problema. Lo proverò. Quindi, se inserisco la query ST_Contains () nella clausola WHERE, l'indice spaziale dovrebbe effettivamente essere utile? Penso di dover riorganizzare il mio script per chiamare ST_Contains nella clausola WHERE. Al momento sto analizzando tutti i poligoni e testandone sempre due separatamente.
MichiMichbeck,

?? stai morendo che un indice spaziale rallenta le cose? Questa è una novità per me perché dove lavoro abbiamo indici spaziali per ogni singolo tavolo e mi chiedo se sia una cattiva pratica
Luffydude,

13

Come diceva unicoletti , l'indice gist nella colonna della geometria funzionerebbe solo se si utilizza ST_Contains () nell'espressione WHERE.

Ad esempio, se desideri conoscere tutti i poligoni che si contengono l'un l'altro, puoi utilizzare qualcosa del genere:

SELECT a.gid, b.gid
FROM table AS a, table as b
WHERE a.gid != b.gid and ST_Contains(a.way, b.way)

In questo caso, a seconda delle dimensioni della tabella e della complessità delle geometrie, l'indice di sintesi dovrebbe fornire una notevole velocità, poiché ST_Contains inizierà filtrando i poligoni confrontando le loro caselle di confine prima di controllarne effettivamente le geometrie complete. Puoi vedere una piccola spiegazione nel tutorial di OpenGeo .


Sì, vedo, ho bisogno di questa query per coinvolgere il test del limite dell'indice. Grazie Alexandre. (Contrassegnerò unicoletti come soluzione, poiché è stato veloce e mi ha risolto il problema)
MichiMichbeck,
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.