Eu tenho dois conjuntos de medições da Terra a partir de dados de satélite, cada um com campos de tempo (mjd para data média juliana) e posições geográficas (GeoPoint, espacial) e estou procurando coincidências entre os dois conjuntos, para que seus horários correspondam a um limite de 3hrs (ou 0,125 dias) e suas distâncias até 200 km um do outro.
Fiz índices para os campos mjd nas tabelas e nas tabelas espaciais.
Quando eu entrei na restrição de tempo, o banco de dados calcula 100.000 correspondências em 8 segundos e calcula as distâncias para todas as 100.000 correspondências nesse período. A consulta fica assim:
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) ) )
E o plano executado é:
Quando ordenadas, 9 das distâncias estavam abaixo de 200 km, portanto há partidas. O problema é que, quando adiciono a restrição de distância e corro isso,
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 um longo tempo. Obviamente, em 8 segundos, ele poderia encontrar 100.000 combinações de tempo, 9 das quais com menos de 200 km, portanto o otimizador deve estar tentando algo sub-ideal. O plano é semelhante ao acima com um filtro nas distâncias (eu acho).
Eu posso forçar o uso do índice espacial com isso:
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) ) )
que leva 3 minutos para encontrar 5 correspondências.
Como digo ao otimizador de consulta para usar primeiro o índice MJD, e depois o índice espacial segundo (ou já é o que está fazendo)? Existe alguma maneira de ajudá-lo dizendo quantas correspondências esperar? Se ele puder calcular 100.000 correspondências com distâncias em 8 segundos, com 9 abaixo de 200 km, a adição do índice espacial não deve torná-lo mais rápido e mais lento?
Obrigado por outras dicas ou idéias.
EDIT: Para responder à pergunta como é o plano sem as dicas, isso (e leva uma eternidade):
Talvez também seja necessário mencionar que existem quase 1 milhão de registros em uma tabela e 8 milhões na outra
fonte
Respostas:
O problema é que ele pode (e conhecendo os índices espaciais, provavelmente assumirá) que o filtro espacial seja muito mais seletivo que o filtro de tempo.
Mas se você tiver alguns milhões de registros em 200 km, poderá ser significativamente pior.
Você está pedindo para encontrar registros dentro de 200 km, que retornam dados ordenados por alguma ordem espacial. Encontrar os registros que estão próximos no tempo significa verificar cada um deles.
Ou então, você está encontrando registros por tempo e obtendo resultados na ordem do tempo. Em seguida, filtrar essa lista para o raio de 200 km é uma questão de verificar cada uma delas.
Se você filtrar os dados em dois intervalos como este, fica difícil aplicar o segundo filtro usando um índice. Talvez seja melhor dizer a ele para não usar o índice espacial se o filtro de tempo for o mais apertado.
Se ambos são grandes individualmente, e apenas juntos eles são estreitos, então você tem um problema mais complexo, que as pessoas tentam resolver há muito tempo e que pode ser bem resolvido por índices que cobrem 3D (e além) espaço. Exceto que o SQL Server não os possui.
Desculpe.
Editar: mais informações ...
Esse é um problema semelhante ao encontrar intervalos de tempo que abrangem um momento específico. Ao procurar os registros que começam antes desse ponto, você tem uma bagunça não ordenada do fim dos tempos - e vice-versa. Se você procurar pessoas na lista telefônica cujos sobrenomes começam com F, não poderá encontrar as pessoas cujos nomes começam com R com muita facilidade. E um índice no primeiro nome também não ajuda pelo mesmo motivo. Encontrar coisas no próximo índice é difícil quando o seu primeiro índice não é uma igualdade.
Agora, se você pudesse mudar seu filtro de data para um filtro de igualdade (ou uma série de filtros de igualdade), poderia ter uma chance, exceto que um índice espacial é um tipo especial de índice e não pode ser usado como o segundo nível em um índice composto.
Então você ficou com uma situação embaraçosa, receio. :(
Editar: Tente:
Observe que estou deliberadamente quebrando a sargabilidade dividindo por 1000 antes de comparar com 200. Quero que este trabalho seja feito na Pesquisa de Chaves.
Lembre-se, você pode evitar a necessidade de pesquisas (e dicas) INCLUINDO o GeoPoint e o Time nos dois índices ix_MJD. Isso certamente tirará parte do calor do plano de consulta.
fonte
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