5 votos

La forma más rápida de eliminar los puntos coincidentes

Espero que alguien pueda ver una manera más rápida de hacer esto, porque en este momento estoy un promedio de 9 horas por carrera para lo que estoy tratando de hacer y así básicamente conseguir mi trasero masticado por el jefe :-)

El escenario

Tenemos una base de datos que se ejecuta bajo PostgreSQL/postgis que se utiliza para gestionar algunos datos cartográficos para la gestión de una flota de transporte.

Dentro de esta base de datos hay varias tablas, pero para mi pregunta aquí, sólo estamos interesados en las "áreas construidas" (también conocidas como zonas limitadas) y en las "velocidades de movimiento" (también conocidas como velocidades) - No puedo entrar en detalles debido a los acuerdos de confidencialidad, etc., pero "zonas limitadas" es una tabla que contiene un número de

MULTIPOLYGONES

cada uno de los cuales representa un área geográfica, y tiene un límite de velocidad asociado que un vehículo puede recorrer mientras esté dentro de los límites de ese polígono.

"velocidades" es una tabla de

PUNTOS

Cada punto sigue la trayectoria de una carretera permitida y se muestrea con un límite de velocidad permitido a intervalos de 1 segundo, lo que representa una carretera por la que un vehículo está autorizado a circular.

En la actualidad, algunas de estas "carreteras permitidas" atraviesan "zonas limitadas" en las que tanto el límite de velocidad de la "carretera permitida" como el de la "zona limitada" son los mismos. Me he encargado de eliminar estos puntos adicionales de la tabla de "Carreteras permitidas" donde coinciden con las condiciones establecidas anteriormente.

Lo que he probado hasta ahora

Mi primer intento fue simplemente seleccionar los puntos, digamos para 40 Mph y ponerlos en una tabla de memoria, luego hacer un bucle sobre esa tabla comparándolos con la tabla 'limitedareas' usando "ST_Intersects" esto no funcionó como se esperaba, y falló en eliminar todos los puntos.

Sin embargo, me dio una idea de la cantidad de puntos que estaba buscando eliminar, y la cuenta superaba fácilmente los 2 millones.

Después de un poco más de toqueteo, y unos cuantos intentos más, finalmente llegué a lo siguiente:

DELETE FROM speeds s
USING limitedzones lz
WHERE ST_Within(s.geometry,lz.geometry)
AND s.speed = lz.speed

y de manera similar utilizó lo siguiente para interrogar y contar:

SELECT s.* FROM speeds s
JOIN limitedzones lz ON ST_Within(s.geometry,lz.geometry)
WHERE s.speed = lz.speed
--LIMIT 10

¡¡¡Ambos funcionan exactamente como espero, pero el select (cuando no está limitado) tarda unas 3 horas en ejecutarse, y el delete más de 9 horas!!!

Si es posible, necesito encontrar una forma más rápida de eliminar estos puntos, ya que es probable que haya más trabajo para añadir esto en un sistema de actualización regular, utilizado ad-hoc con frecuencia para mantener la base de datos en orden.

Tengo buenos índices tanto B-Tree (gist) como regulares en todas las columnas, y cuando las tablas individuales se utilizan por sí solas, todo es agradable y rápido, así que sé que es la unión de 2 tablas lo que me está causando la ralentización.

Cualquier sugerencia es bienvenida, e incluso estoy abierto a hacer esto usando una función / procedimiento personalizado si es necesario.

2voto

rkthkr Puntos 6651

No sé mucho de PostGIS, pero sí sé que estaba teniendo problemas similares de "Borrar está tardando días" con Oracle. Pregunté en stackoverflow ( Manera óptima de SUPRIMIR las filas especificadas de Oracle ) y la respuesta proporcionada es órdenes de magnitud más rápidas que el camino "obvio" que usted y yo seguiríamos ( delete from... ).

Por lo tanto, mi sugerencia sería algo así:

CREATE TABLE PURGE_IDS NOLOGGING
AS
    SELECT s.ID FROM speeds s
    JOIN limitedzones lz ON ST_Within(s.geometry,lz.geometry)
    WHERE s.speed = lz.speed;

DELETE FROM speeds WHERE ID IN (SELECT ID FROM PURGE_IDS);

DROP TABLE PURGE_IDS;

Por supuesto, esto es asumiendo que PostGIS obtiene el mismo aumento de velocidad que Oracle. El problema entonces es hacer que el SELECT más rápido que no puedo ayudar (es posible que desee probar la lista de correo PostGIS para eso).

Yo sugeriría probar la velocidad ejecutando cada uno de los comandos por separado y cronometrándolos.


Si eso no funciona, puedes preguntar en stackoverflow.com una pregunta puramente postGreSQL similar a mi pregunta sobre Oracle y tratar el SELECT como un problema diferente.

2voto

axk Puntos 2147
  • ¿Está seguro de que tiene índices espaciales en el speeds y limitedzones ¿mesas?

  • ¿Las mesas han sido analyzed (recopilar estadísticas para que los índices funcionen eficazmente)?

  • Si tiene un índice espacial, es st_within ¿usándolos? Que yo recuerde, no lo hace, así que puedes asegurarte de que el índice espacial se utiliza añadiendo la cláusula que requiere la intersección de BBOX:

    DELETE FROM speeds s
    USING limitedzones lz
    WHERE s.geometry && lz.geometry and ST_Within(s.geometry,lz.geometry)
    AND s.speed = lz.speed

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X