Cómo optimizar una consulta para que primero busque un índice y luego otro índice después de eso


12

Tengo dos conjuntos de mediciones de la tierra a partir de datos satelitales, cada uno con campos de tiempo (mjd para la fecha media juliana) y posiciones de geografía (GeoPoint, espacial) y estoy buscando coincidencias entre los dos conjuntos de modo que sus tiempos coincidan con un umbral de 3 horas (o .125 días) y sus distancias a menos de 200 km entre sí.

He hecho índices para los campos mjd en ambas tablas y tablas espaciales.

Cuando acabo de unirme a la restricción de tiempo, la base de datos calcula 100,000 coincidencias en 8 segundos y calcula las distancias para todas las 100,000 coincidencias en ese tiempo. La consulta se ve así:

select top 100000 h.Time, m.Time, h.GeoPoint.STDistance(m.GeoPoint)/1000.0
from L2V5.dbo.header h join L2.dbo.MLS_Header m
on h.mjd between m.mjd-.125 and m.mjd+.125
option( table hint ( h, index(ix_MJD) ), table hint( m, index(ix_MJD) ) )

Y el plan ejecutado es:

Solo restricción mjd

Cuando se clasificaron, 9 de las distancias eran inferiores a 200 km, por lo que hay coincidencias. El problema es que cuando agrego la restricción de distancia y ejecuto esto en su lugar,

select top 10 h.Time, m.Time, h.GeoPoint.STDistance(m.GeoPoint)/1000.0
from L2V5.dbo.header h join L2.dbo.MLS_Header m
on h.mjd between m.mjd-.125 and m.mjd+.125
and h.GeoPoint.STDistance(m.GeoPoint)<200000
option( table hint ( h, index(ix_MJD) ), table hint( m, index(ix_MJD) ) )

desaparece por mucho tiempo. Obviamente, en 8 segundos, podría encontrar 100,000 coincidencias de tiempo, 9 de las cuales estaban a menos de 200 km, por lo que el optimizador debe intentar algo subóptimo. El plan es similar al anterior con un filtro en las distancias (supongo).

con restricción espacial, sin filtro espacial

Puedo forzar el uso del índice espacial con esto:

select top 5 h.Time, m.Time, h.GeoPoint.STDistance(m.GeoPoint)/1000.0 
from L2V5.dbo.header h join L2.dbo.MLS_Header m 
on h.GeoPoint.STDistance(m.GeoPoint)<200000
and h.mjd between m.mjd-.125 and m.mjd+.125 
option( table hint ( h, index(ix_MJD), index(ix_GeoPoint) ), table hint( m, index(ix_MJD) ) )

ambas restricciones con ambos índices

que luego toma 3 minutos para encontrar 5 coincidencias.

¿Cómo le digo al optimizador de consultas que use primero la búsqueda del índice MJD, y luego el índice espacial (o es eso lo que ya está haciendo) y hay alguna forma de ayudarlo diciéndole cuántas coincidencias esperar? Si puede calcular 100,000 coincidencias con distancias en 8 segundos que tienen 9 por debajo de 200 km, ¿no debería la adición del índice espacial hacerlo más rápido, no más lento?

Gracias por cualquier otro consejo o idea.

EDITAR: Para responder a la pregunta de cómo se ve el plan sin las pistas, esto (y lleva una eternidad):

sin pistas

Quizás también valga la pena mencionar que hay casi 1 millón de registros en una tabla y 8 millones en la otra.


¿Qué aspecto tiene su plan de consultas si elimina esas sugerencias?
Zane

@Zane, edité la publicación y agregué el plan de consulta sin pistas. Reemplaza las búsquedas con escaneos y el tiempo es abismal.
user261963

Respuestas:


6

El problema es que podría (y conociendo los índices espaciales, probablemente lo hará) asumir que el filtro espacial será mucho más selectivo que el filtro de tiempo.

Pero si tiene unos pocos millones de registros dentro de los 200 km, entonces podría ser significativamente peor.

Le está pidiendo que encuentre registros dentro de los 200 km, que devuelve datos ordenados por algún orden espacial. Encontrar los registros que están cerca en el tiempo significa verificar cada uno.

O bien, está buscando registros por tiempo y obtiene resultados en orden de tiempo. Luego, filtrar esta lista al radio de 200 km es cuestión de verificar cada uno.

Si filtra los datos en dos rangos como este, será difícil aplicar el segundo filtro usando un índice. Es mejor que le diga que no use el índice espacial si el filtro de tiempo es el más ajustado.

Si ambos son grandes individualmente, y solo juntos son ajustados, entonces tienes un problema más complejo, uno que la gente ha intentado resolver durante mucho tiempo, y que podría resolverse bien mediante índices que cubran 3D (y más allá) espacio. Excepto que SQL Server no los tiene.

Lo siento.

Editar: más información ...

Este es un problema similar a la búsqueda de rangos de tiempo que cubren un punto particular en el tiempo. Cuando busca los registros que comienzan antes de ese punto, entonces tiene un desorden desordenado de los tiempos finales, y viceversa. Si busca personas en la guía telefónica cuyos apellidos comienzan con F, no puede esperar encontrar a las personas cuyos nombres comienzan con R muy fácilmente. Y un índice sobre el primer nombre tampoco ayuda por la misma razón. Encontrar cosas en el siguiente índice es difícil cuando su primer índice no es una igualdad.

Ahora, si pudieras cambiar tu filtro de fecha en un filtro de igualdad (o una serie de filtros de igualdad), entonces podrías tener una posibilidad, excepto que un índice espacial es un tipo especial de índice y no puede usarse como el segundo nivel en Un índice compuesto.

Entonces me temo que tienes una situación incómoda. :(

Editar: Probar:

select top 100000 h.Time, m.Time, h.GeoPoint.STDistance(m.GeoPoint)/1000.0
from L2V5.dbo.header h join L2.dbo.MLS_Header m
on h.mjd between m.mjd-.125 and m.mjd+.125
where h.GeoPoint.STDistance(m.GeoPoint)/1000.0 < 200
option( table hint ( h, index(ix_MJD) ) );

Tenga en cuenta que deliberadamente estoy rompiendo la sargabilidad dividiendo entre 1000 antes de comparar con 200. Quiero que este trabajo se realice en la búsqueda de claves.

Eso sí, podría evitar la necesidad de las búsquedas (y las sugerencias) INCLUYENDO GeoPoint y Time en ambos índices ix_MJD. Eso ciertamente eliminará parte del calor del plan de consulta.


No sé si cambia algo, pero el filtro de tiempo es mucho más selectivo.
user261963

Okay. Entonces, ¿es aceptable ubicar todas las filas coincidentes en el tiempo y luego verificar cada ubicación sin el índice?
Rob Farley,

... entonces el plan se parece al plan original, pero tiene un predicado o filtro adicional.
Rob Farley

Sugirió algunos cambios con una edición rápida. No necesitas insinuar sobre m, solo h. Aunque si puede cambiar a cuál está agregando 1/8, para asegurarse de que está modificando la columna de la tabla más pequeña y usando esos valores para buscar en la más grande, eso también ayudará. Si h es 8M ym es 1M, deje el predicado ENTRE y sugiera solo h. Si es al revés, cambie su predicado y pista (pero mejor que cambiar la pista es agregar esas columnas a su índice).
Rob Farley,

Sacar todas las sugerencias de la tabla parece funcionar mejor al final, siempre que haga h entre my no al revés. La consulta ya no usa los índices de GeoPoint, pero de todos modos no los estaba usando de manera eficiente. Incluí la columna GeoPoint en el índice MJD y eso ayudó mucho. select top 10000 h.Time, m.Time, m.GeoPoint.STDistance(h.GeoPoint), h.mjd-m.mjd from L2V5.dbo.header h join L2.dbo.MLS_Header m on m.GeoPoint.STDistance(h.GeoPoint)<200000 and m.mjd between h.mjd-.125 and h.mjd+.125 order by h.mjd
user261963
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.