Estou tentando começar com um projeto de pesquisa geográfica que encontrará todos os pontos de referência nos 10 km / milhas (não importantes para esta história) de um ponto de referência específico.
Por exemplo, digamos que eu tenha um banco de dados com 1.000.000 de pontos de referência. Para encontrar todos os pontos de referência no intervalo de 10 milhas de um ponto de referência com determinadas coordenadas, eu precisaria calcular a distância entre um ponto de referência da minha pesquisa e 1.000.000 pontos de referência.
Existe uma maneira melhor de fazer isso?
A alternativa que eu estava pensando é categorizar pontos de referência como país, região, cidade, bairro, empresa, histórico etc. de tal maneira que as empresas possam fazer parte de uma vizinhança ou cidade. A cidade faz parte de uma região, país, etc. Isso pode restringir uma lista de cálculos, mas ainda parece haver muito trabalho a fazer para que a pesquisa seja rápida e precisa.
A API do Google Maps poderia ajudar?
fonte
Respostas:
Desde o SQL Server 2008, existe um tipo de dados geográficos que armazena locais (pares lat / lon) e facilita a gravação de consultas relacionadas ao local.
Existe uma resposta StackOverflow existente que discute isso em profundidade.
Uma consulta básica para encontrar os 7 itens mais próximos :
Uma consulta básica para encontrar tudo dentro de 100m (segunda resposta à pergunta)
fonte
Use um banco de dados com suporte para consultas GIS (sistemas de informações geográficas) . A maioria dos bancos de dados suporta isso de imediato ou possui extensões, mas os detalhes serão específicos do banco de dados (na resposta , Flater mostra a sintaxe do SQL Server).
Se você precisar implementar essas consultas na sua aplicação, poderá implementar uma estrutura de dados que permita consultas espaciais, por exemplo, uma árvore kd . É como uma árvore de pesquisa binária, exceto que cada nível da árvore é particionado em uma dimensão de coordenada diferente. Isso permite restringir a pesquisa a um conjunto menor de candidatos possíveis. Efetivamente, você traduz sua pesquisa "raio de 10 km" em limites para cada dimensão de coordenada e os aperta conforme recua na árvore.
fonte
Sim, existe uma maneira melhor. Você precisa usar um índice espacial . Esses índices organizam metadados sobre geometrias para filtrar geometrias distantes muito rapidamente, economizando muitos ciclos de CPU, evitando os cálculos que você descreve. Você não deve se preocupar em implementar um, pois todos os principais bancos de dados relacionais fornecem um tipo de geometria espacial e índices para acompanhá-los.
O que você deseja examinar são consultas "à distância" (consultas para geometrias a uma certa distância de outra geometria). Estes são muito padrão e muito um problema resolvido e são possíveis em todos os bancos de dados acima (e incorporados em vários):
ST_DWithin
STDistance
(Não está claro que o uso de índice na versão geográfica 3D dessa função é suportada)SDO_WITHIN_DISTANCE
(isso não diz explicitamente que ele acionará o uso do índice. Eu daria uma checada no plano de consulta. Pode ser necessário aplicar umSDO_FILTER
para fazê-lo usar o índice.)Solução alternativa para acionar o uso do índice
No pior caso onde você tem problemas para obter o sistema para usar o índice espacial com estas consultas, você pode adicionar um filtro adicional. Você criaria uma caixa delimitadora quadrada com lados de comprimento 2 * (distância de pesquisa) centralizada no ponto de pesquisa e compararia as caixas delimitadoras das geometrias da tabela com essa antes de verificar a distância real. É o que o PostGIS '
ST_DWithin
acima faz internamente de qualquer maneira.Distância em SIG
Embora os índices espaciais sejam fantásticos e absolutamente a solução certa para o seu problema, o cálculo da distância pode ser logicamente complicado. Em particular, você precisa se preocupar com em qual projeção (basicamente todos os parâmetros do sistema de coordenadas) seus dados são armazenados. A maioria das projeções 2D (outras coisas que não os sistemas de coordenadas angulares, como as várias projeções latinas / longas) distorcem significativamente o comprimento. Por exemplo, a projeção Web Mercator (usada pelo Google, Bing e todos os principais fornecedores de mapas de base) expande áreas e distâncias cada vez mais à medida que a localização se afasta do do equador . Posso estar errado, pois não sou formalmente formado em SIG, mas o melhor que já vi para projeções em 2D são algumas específicas que prometem distâncias corretas de umponto único e constante em todo o mundo. (Não, não é prático usar uma projeção diferente para cada consulta; isso tornaria seus índices inúteis.)
A linha inferior é que você precisa ter certeza de que sua matemática está correta. A maneira mais simples de fazer isso da perspectiva do desenvolvimento é usar projeções angulares (geralmente chamadas de "geográficas") e funções que suportam a matemática usando um modelo de esferóide, mas esses cálculos são um pouco mais caros do que os equivalentes 2D e alguns bancos de dados podem não suportar a indexação deles. Se você pode obter um desempenho aceitável usando-os, esse provavelmente é o caminho a percorrer. Outra opção comum são as projeções regionais (como zonas UTM) que obtêm distâncias e áreas muito próximas da correção, se seus dados estiverem confinados a uma parte específica do mundo. O melhor para o seu aplicativo dependerá de seus requisitos específicos,
Isso se aplica mesmo se você não usar índices espaciais incorporados. Seus dados têm alguma projeção, independentemente de qual tecnologia ou técnica você está usando ou usa no futuro, e já está afetando as consultas e cálculos que você está fazendo no momento.
fonte
Concordo que, se possível, usar suporte específico em um banco de dados seria a maneira mais sensata de fazer isso.
No entanto, se eu tivesse que fazer isso em um banco de dados sem suporte específico, começaria consultando um quadrado que envolva a circulação, por exemplo (y> (y1 - rad)) AND (y <(y1 + rad)) AND (x> ( x1 - rad)) AND (x <(x1 + rad)). Supondo que seus pontos tenham praticamente a distribuição de consultas por um quadrado, você obterá suas correspondências verdadeiras e cerca de 30% de falsas extra. Você pode selecionar as correspondências falsas.
fonte
x
ey
. (Talvez combinados, talvez separar Eu perfil um pouco para descobrir qual funciona melhor na prática..)BETWEEN
consultas. Não vejo por que, na pior das hipóteses, você não pode ter dois índices e, em seguida, os resultados filtrados de cada índice são reunidos. (Isso é algo que os RDBMSs fazem internamente quando consideram que vale a pena usar vários índices.) Se um índice combinado funcionar, ele deve filtrar uma dimensão inteiramente no primeiro nível e, em seguida, diminuir rapidamente no segundo nível.y between -68 and -69 and x between 10 and 11
, mas do índice de curso espacial fazer um trabalho melhor para essa tarefa