2010-08-12 19 views
10

Estoy trabajando en mover algunas capacidades de búsqueda espacial de Postgres con PostGIS a SQL Server y estoy viendo un rendimiento bastante terrible, incluso con índices.¿Por qué mis búsquedas espaciales son más lentas en SQL Server que PostGIS?

Mis datos es de alrededor de un millón de puntos, y quiero averiguar cuál de estos puntos están dentro de formas dadas, por lo que la consulta es como la siguiente:

DECLARE @Shape GEOMETRY = ... 
SELECT * FROM PointsTable WHERE Point.STWithin(@Shape) = 1 

Si selecciono una bastante pequeña forma, A veces puedo obtener segundos segundos, pero si mi forma es bastante grande (que a veces son), puedo obtener tiempos de más de 5 minutos. Si ejecuto las mismas búsquedas en Postgres, siempre están por debajo de un segundo (de hecho, casi todas tienen menos de 200 ms).

He intentado varios tamaños de cuadrícula en mis índices (todos altos, todos medianos, todos bajos), diferentes celdas por objeto (16, 64, 256) y no importa lo que haga, los tiempos permanecen bastante constantes. Me gustaría probar más combinaciones, pero ni siquiera sé qué dirección tomar. Más celdas por objeto? ¿Menos? ¿Alguna extraña combinación de tamaños de cuadrícula?

He visto mis planes de consulta y siempre están usando el índice, simplemente no está ayudando en absoluto. Incluso he intentado sin el índice, y no es mucho peor.

¿Hay algún consejo que alguien pueda dar sobre esto? Todo lo que puedo encontrar sugiere que "no podemos darle ningún consejo sobre índices, simplemente pruebe todo y tal vez uno funcione", pero demorar 10 minutos en crear un índice, hacerlo a ciegas es una gran pérdida de tiempo.

EDITAR: También publiqué esto en a Microsoft forum. He aquí alguna información que pedían allí:

El mejor índice de trabajo que pude conseguir fue la siguiente:

CREATE SPATIAL INDEX MapTesting_Location_Medium_Medium_Medium_Medium_16_NDX 
    ON MapTesting (Location) 
USING GEOMETRY_GRID 
    WITH (
    BOUNDING_BOX = (-- The extent of our data, data is clustered in cities, but this is about as small as the index can be without missing thousands of points 
     XMIN = -12135832, 
     YMIN = 4433884, 
     XMAX = -11296439, 
     YMAX = 5443645), 
    GRIDS = (
     LEVEL_1 = MEDIUM, 
     LEVEL_2 = MEDIUM, 
     LEVEL_3 = MEDIUM, 
     LEVEL_4 = MEDIUM), 
    CELLS_PER_OBJECT = 256 -- This was set to 16 but it was much slower 
) 

he tenido algunos problemas para conseguir el índice utilizado, pero esto es diferente.

Para estas pruebas realicé una búsqueda de prueba (la que figura en mi publicación original) con una cláusula WITH (INDEX (...)) para cada uno de mis índices (probando varias configuraciones para el tamaño de la cuadrícula y las celdas por objeto) y uno sin ninguna pista. También ejecuté sp_help_spatial_geometry_index usando cada índice y la misma forma de búsqueda. El índice mencionado anteriormente funcionaba más rápido y también se incluyó como el más eficaz en sp_help_spatial_geometry_index.

Cuando se ejecuta la búsqueda consigo estas estadísticas:

(1 row(s) affected) 
Table 'MapTesting'. Scan count 0, logical reads 361142, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'extended_index_592590491_384009'. Scan count 1827, logical reads 8041, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 

(1 row(s) affected) 

SQL Server Execution Times: 
    CPU time = 6735 ms, elapsed time = 13499 ms. 

También he intentado usar como puntos aleatorios de datos (ya que no puedo dar a conocer nuestros datos reales), pero resulta que esta búsqueda es realmente rápido con datos aleatorios. Esto nos lleva a creer que nuestro problema es cómo funciona el sistema de cuadrícula con nuestros datos.

Nuestros datos son direcciones en todo el estado, por lo que hay algunas regiones de muy alta densidad, pero la mayoría de los datos son escasos. Creo que el problema es que ninguna configuración para los tamaños de cuadrícula funciona bien para ambos. Con cuadrículas establecidas en HIGH, el índice devuelve demasiadas celdas en áreas de baja densidad, y con grillas establecidas en LOW, las cuadrículas son inútiles en áreas de alta densidad (en MEDIUM, no es tan malo, pero aún no es bueno en ninguno).

Puedo utilizar el índice, simplemente no está ayudando. Cada prueba se ejecutó con "mostrar plan de ejecución real" activado, y siempre muestra el índice.

+0

+1: Me gustaría saber también. –

+0

¿Están sus millones de puntos de datos almacenados como geometría (plana, espacio euclidiano) o geografía (coordenadas redondas y terrenales)? Si está mezclando geometría y geografía, va a introducir un golpe de rendimiento para la conversión matemática. – mwalker

+0

@Mwalker, es todo geometría, y no creo que puedas mezclarlos y combinarlos de todos modos. –

Respuesta

3

Éstos son algunos comentarios sobre las extensiones espaciales de SQL Server y cómo asegurarse de que el índice se utiliza de manera eficiente:

Al parecer, el planificador tiene dificultades para construir un buen plan si no conoce la geometría real durante el tiempo de análisis. El autor sugiere insertar exec sp_executesql:

Reemplazar:

-- does not use the spatial index without a hint 
declare @latlonPoint geometry = geometry::Parse('POINT (45.518066 -122.767464)') 
select a.id, a.shape.STAsText() 
from zipcodes a 
where a.shape.STIntersects(@latlonPoint)=1 
go 

con:

-- this does use the spatial index without using a hint 
declare @latlonPoint geometry = geometry::Parse('POINT (45.518066 -122.767464)') 
exec sp_executesql 
N'select a.id, a.shape.STAsText() 
from zipcodes a 
where a.shape.STIntersects(@latlonPoint)=1', N'@latlonPoint geometry', @latlonPoint 
go 
+0

Sin embargo, mi índice espacial está siendo usado. Pulso "Incluir plan de ejecución real" y muestra el índice espacial que se está utilizando. –

+0

Intenté esta sugerencia solo para estar seguro y los tiempos y el plan de ejecución fueron los mismos. –

+0

+1 informativo, incluso si no resolvió el problema del OP –

1

Mi reacción visceral es "porque Microsoft no ha tomado la molestia de hacerlo rápido, porque no es una Empresa Característica". Tal vez estoy siendo cínico.

No estoy seguro de por qué estás migrando lejos de Postgres tampoco.

+0

Sospecho que tiene más que ver con que es una característica nueva; Escuché que se supone que lo harán mucho mejor en la próxima versión. Lo que me confunde es que no he escuchado nada acerca de que sea lento, así que me preocupa que me esté perdiendo algo. –

+1

Después de trabajar con índices espaciales en SQL Server estoy comenzando a esto, esto es cierto. –

0

no estoy familiarizado con las consultas espaciales, pero podría ser un problema de consulta con parámetros

intentar escribir una consulta (sin utilizar parámetros) con un valor fijo (utilizar un valor que realiza lenta con la consulta con parámetros) y ejecutarlo. Compare los tiempos con la versión parametrizada. Si es mucho más rápido, su problema son las consultas parametrizadas.

Si lo anterior es mucho más rápido, entonces construiría dinámicamente su cadena sql con los valores de los parámetros incrustados en la cadena, de esa manera puede eliminar los parámetros que causan problemas.

+0

Parece bastante improbable que la parametrización de consultas sea el problema aquí. El OP dijo: _ "Si selecciono una forma bastante pequeña, a veces puedo obtener sub-segundos veces, pero si mi forma es bastante grande (que a veces lo son), puedo obtener tiempos de más de 5 minutos." _ ** 1 . ** El rendimiento de la consulta parece verse afectado por las propiedades espaciales de la geometría de la consulta. ** 2. ** Incluso si piensa que las consultas parametrizadas podrían ser lentas, no deberían convertir una consulta rápida en una que requiera más de 5 minutos (!) Para ejecutarse ... No puedo pensar en ninguna explicación razonable de por qué tendría ese efecto. – stakx

1

¿Ha configurado correctamente su índice espacial? ¿Es correcto su cuadro delimitador? ¿Están todos los puntos adentro? En su caso, probablemente HHMM para GRIDS funcionaría mejor (dependiendo nuevamente de una caja de bouding).

¿Puedes tratar de usar sp_help_spatial_geometry_index, para ver qué pasa? http://msdn.microsoft.com/en-us/library/cc627426.aspx

Intente utilizar la operación de filtro y díganos qué números de perfunción obtiene? (ejecuta solo el filtro primario (use index) sin pasar por el filtro secundario (operación espacial real))

Algo está mal con su configuración. Spatial es, de hecho, una nueva característica, pero no es tan malo.

+0

He probado todas las combinaciones de dos tamaños (LLLL, LLMM, LLHH, MMLL, etc.) y lo mejor era MMMM con 256 celdas por objeto.'sp_help_spatial_geometry_index' dijo que el filtro primario era 90% eficiente, lo que creo que podría ser el problema (otros fueron tan bajos como 70%). 'Filter' fue mucho más rápido que' STIntersects', pero aún 2-5 veces más lento que Postgres (y no tan preciso). –

+0

Creemos que el problema es que nuestros datos son bastante escasos con las regiones de alta densidad, por lo que el enfoque del tamaño de la cuadrícula estática no es útil. Si establecemos las grillas en alto, el índice es demasiado específico en áreas dispersas, pero si lo configuramos en bajo, el índice es inútil en áreas de alta densidad. –

+0

Luego intente configurar múltiples índices espaciales alrededor de cada región de alta densidad. O al menos rompa todo Estados Unidos en pocas áreas grandes. Espero que tengas la mayoría de tus datos en la costa este y oeste. – Desinderlase

2

Creo que STIntersects está mejor optimizado para usar el índice que tendría un mejor rendimiento que STWithin, especialmente para formas más grandes.

+0

Probamos ambas cosas y no hizo ninguna diferencia. –

+0

¿Podría publicar la información del plan después de configurar el perfil de estadísticas de conjunto, para la consulta STIntersects? – Giri

1

Usted puede tratar de dividirlo en dos pases:

  1. seleccionar a los candidatos en una tabla temporal w/.Filter().
  2. candidatos de consulta w/.STWithin().

por ejemplo:

SELECT * INTO #this FROM PointsTable WHERE Point.Filter(@Shape) = 1 
SELECT * FROM #this WHERE Point.STWithin(@Shape) = 1 

(reemplazando SELECT * con sólo las columnas reales que necesita para reducir la E/S)

Este tipo de micro-optimización no debería ser necesario, pero tengo visto mejoras decentes de rendimiento antes. Además, podrá evaluar cuán selectivo es su índice por la relación de (1) a (2).

3

Acabo de pasar el día en un problema similar. En particular, estamos haciendo una consulta de tipo punto en polígono, donde había un conjunto relativamente pequeño de polígonos, pero cada polígono era grande y complejo.

solución resultó ser de la siguiente manera, para el índice espacial en la tabla polígono:

  1. Uso "rejilla geometría auto" en lugar de la antigua MMLL etc. Esto da 8 niveles como máximo en lugar de la vieja 4, y la configuración es automática. 'celdas por objeto' Y ...
  2. SET para 2000 o 4000. (No es una cosa fácil de adivinar, dado que el valor predeterminado es 16!)

Esto marcó una gran diferencia. Era 10 veces más rápido que un índice espacial en la configuración predeterminada, y 60 veces más rápido que ningún índice en absoluto.

1

Problemas de eficiencia de implementación a un lado El servidor SQL usa Quadtree index mientras que PostGIS usa el índice R-tree.

R-tree es en la mayoría de los casos el mejor algoritmo, especialmente para grandes conjuntos de datos con diferentes tamaños de geometría.

Cuestiones relacionadas