Índice espacial PostgreSQL / PostGIS: sin velocidad

15

Tengo una tabla espacial en una base de datos PostgreSQL / PostGIS. Cada fila en ella representa un polígono. Es de la siguiente forma:

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

La columna geométrica es "camino" que contiene la geometría de un polígono. En WKT es: POLYGON (('....')). Estoy haciendo muchas consultas ST_Contains en esta tabla, para probar si dos polígonos están contenidos entre sí, por ejemplo:

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

Me preguntaba cómo acelerar esta consulta y agregué un índice espacial en la tabla:

CREATE INDEX table_way_gist ON table USING gist(way);

Pero en realidad no veo una aceleración. Creo el índice DESPUÉS de llenar la tabla con todos los polígonos ANTES de hacer las consultas ST_Contains. ¿Se debe agregar el índice antes de llenar una tabla? ¿Hay requisitos especiales en la tabla para trabajar con el índice? La proyección (cuadrícula) de la forma de columna geométrica se establece en 900913.

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

MichiMichbeck
fuente

Respuestas:

16

El índice más eficiente para la consulta expresada en su pregunta es el de gid, ya que es la única columna que aparece en una expresión where:

 CREATE INDEX table_gid ON table (gid);

Puede soltar el índice de forma segura, ya que solo consumirá espacio y ralentizará las inserciones / actualizaciones / eliminaciones.

Larga explicación

Como dije, el índice más efectivo en su caso es el de gid, ya que permitirá que el motor db recupere filas más rápido (la recuperación suele ser la parte más lenta del proceso). Después de eso, probablemente calculará mejor el resultado de la

  ST_Contains(a.way, b.way)

expresión sin mirar el índice. La razón es que el planificador de consultas probablemente estimará que el costo adicional de buscar el índice esencial en ambas columnas versus buscar los valores a.way y b.way directamente no vale la pena ya que el número total de filas para buscar es probablemente muy pequeño, especialmente si el índice es único.

Como regla general, recuerde que el planificador probablemente favorecerá una exploración de tabla sobre una exploración de índice para conjuntos de datos pequeños (los tamaños de los conjuntos de datos se estiman mirando las estadísticas de la tabla).

unicoletti
fuente
Eso hace que el problema sea más claro para mí. Voy a intentarlo. Entonces, si pongo la consulta ST_Contains () en la cláusula WHERE, ¿el índice espacial debería ser útil? Creo que tengo que reorganizar mi script para llamar a ST_Contains dentro de la cláusula WHERE. En este momento estoy iterando a través de todos los polígonos y siempre pruebo dos de ellos por separado.
MichiMichbeck
?? ¿Estás diciendo que un índice espacial ralentiza las cosas? Eso es nuevo para mí porque donde trabajo tenemos índices espaciales para cada tabla y me pregunto si es una mala práctica
Luffydude
13

Como dijo unicoletti , el índice esencial en la columna de geometría solo funcionaría si usa ST_Contains () en la expresión WHERE.

Por ejemplo, si desea conocer todos los polígonos que se contienen entre sí, puede usar algo como esto:

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

En este caso, dependiendo del tamaño de su tabla y la complejidad de sus geometrías, el índice esencial debería proporcionar una aceleración significativa, ya que ST_Contains comenzará filtrando los polígonos comparando sus cuadros de límite antes de verificar realmente sus geometrías completas. Puede ver una pequeña explicación en el Tutorial de OpenGeo .

Alexandre Neto
fuente
Sí, ya veo, necesito esta consulta para involucrar la prueba de límite de índice. Gracias Alexandre. (Marcaré unicoletti como solución, ya que fue rápido y me aclaró el problema)
MichiMichbeck