La mesa T_PIN
tiene 300,000 pines y T_POLYGON
36,000 polígonos. T_PIN
tiene este índice:
CREATE SPATIAL INDEX [T_PIN_COORD] ON [dbo].[T_PIN]
(
[Coord]
)USING GEOGRAPHY_GRID
WITH (GRIDS =(LEVEL_1 = HIGH,LEVEL_2 = HIGH,LEVEL_3 = HIGH,LEVEL_4 = HIGH),
CELLS_PER_OBJECT = 128, PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
ON [PRIMARY];
T_POLYGON
tiene:
CREATE SPATIAL INDEX [T_POLYGON_COORD] ON [dbo].[T_POLYGON]
(
[COORD]
)USING GEOGRAPHY_GRID
WITH (GRIDS =(LEVEL_1 = HIGH,LEVEL_2 = HIGH,LEVEL_3 = HIGH,LEVEL_4 = HIGH),
CELLS_PER_OBJECT = 128, PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
ON [PRIMARY];
Una consulta para encontrar la intersección T_PIN
y T_POLYGON
tarda más de 45 minutos en ejecutarse:
SELECT COUNT(*)
FROM T_PIN
INNER JOIN T_POLYGON
ON T_PIN.Coord.STIntersects(T_POLYGON.COORD) = 1;
El resultado es 4.438.318 filas.
¿Cómo puedo acelerar esta consulta?
Respuestas:
Primero, verifique si se está utilizando un índice espacial mirando el plan de ejecución de la consulta y vea si hay un elemento de Búsqueda de índice agrupado (espacial).
Suponiendo que se esté utilizando, puede intentar agregar un filtro secundario / simplificado basado en un cuadro delimitador con polígonos simplificados para verificar primero. Las coincidencias con estos polígonos simplificados podrían ejecutarse a través del filtro primario para obtener los resultados finales.
1) Agregue una nueva columna de geografía y geometría a la tabla [dbo]. [T_POLYGON]:
2) Cree los polígonos del cuadro delimitador (esto implica una conversión inicial a geometría para aprovechar STEnvelope ()):
3) Crear un índice espacial en la columna de geografía simplificada
4) Obtenga las intersecciones contra esta columna de geografía simplificada, luego filtre nuevamente en los tipos de datos de geografía coincidentes. Aproximadamente, algo como esto:
EDITAR : puede reemplazar (1) y (2) con esta columna calculada y persistente. crédito a Paul White por la sugerencia.
fuente
Las consultas como esta suelen llevar mucho tiempo debido a la complejidad de los polígonos. He visto costas complejas (por ejemplo) que tardan años en probar puntos que están cerca de sus límites, teniendo que hacer zoom en muchos niveles para encontrar si un punto está dentro o fuera.
... para que puedas probar
.Reduce()
los polígonos, para ver si eso ayuda.Y para obtener más información sobre esa función, consulte http://msdn.microsoft.com/en-us/library/cc627410.aspx
fuente
Según los documentos de Microsoft, los índices espaciales se usarán con los tipos de geografía en los siguientes métodos cuando aparecen al comienzo de un predicado de comparación con una
WHERE
cláusula:STIntersects
STDistance
STEquals
Solo los métodos de tipos de geometría (lista restringida) activarán el uso del índice espacial
JOIN ... ON
, así que cambie su código para usarloWHERE geog1.STIntersects(geog2) = 1
y eso debería mejorar la velocidad.También recomiendo tomar consejos en la respuesta de g2server y agregar lo siguiente para filtrar y agregar índice espacial en él
entonces podría tener una consulta como la siguiente (escribí esta publicación rápidamente y aún no la he probado, esto es solo algo para probar porque vi que su consulta y las respuestas más altas publicadas usan JOIN ON espacial op = 1 que no usará un índice espacial):
FYI: Lo anterior no funciona si
SimplePolysGeog
termina superpuesto (como en un pin puede estar en dos geogs simplificados, solo ejecuté esto en personas en recintos en un estado y dado que los polys normales comparten límites, los cuadros delimitadores se superponen), por lo que en la mayoría de los usos casos, arrojará un error que la subconsulta arrojó más de un resultado.Del resumen de índices espaciales de MS Docs :
La siguiente consulta funcionará si se
SimplePolysGeogs
superpone:fuente