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.