Estoy tratando de comenzar con un proyecto de búsqueda geográfica que encontrará todos los puntos de referencia en los 10 km / millas (no importantes para esta historia) de un punto de referencia particular.
Entonces, por ejemplo, digamos que tengo una base de datos de 1,000,000 de puntos de referencia. Para encontrar todos los puntos de referencia en el rango de 10 millas de un punto de referencia con ciertas coordenadas, tendría que calcular la distancia entre un punto de referencia de mi búsqueda y 1,000,000 de puntos de referencia.
¿Hay una mejor manera de hacer eso?
La alternativa que estaba pensando es categorizar puntos de referencia como país, región, ciudad, vecindario, negocios, histórico, etc., de tal manera que los negocios puedan ser parte de un vecindario o ciudad. La ciudad es parte de una región, un país, etc. Esto puede reducir una lista de cálculos, pero aún así parece que se necesita mucho trabajo para que la búsqueda sea rápida y precisa.
¿Podría ayudar la API de Google Maps?
fuente
Respuestas:
Desde SQL Server 2008, existe un tipo de datos de geografía que almacena ubicaciones (pares de lat / lon) y le facilita la escritura de consultas relacionadas con la ubicación.
Existe una respuesta StackOverflow existente que analiza esto en profundidad.
Una consulta básica para encontrar los 7 elementos más cercanos :
Una consulta básica para encontrar todo dentro de los 100 m (segunda respuesta a la pregunta)
fuente
Utilice una base de datos con soporte para consultas SIG (sistemas de información geográfica) . La mayoría de las bases de datos admiten esto directamente o tienen extensiones, pero los detalles serán específicos de la base de datos (en su respuesta , Flater muestra la sintaxis para el servidor SQL).
Si necesita implementar tales consultas dentro de su aplicación, puede implementar una estructura de datos que permita consultas espaciales, por ejemplo, un árbol kd . Esto es como un árbol de búsqueda binario, excepto que cada nivel de las particiones del árbol en una dimensión de coordenadas diferente. Esto le permite restringir la búsqueda a un conjunto más pequeño de candidatos factibles. Efectivamente, traduce su búsqueda "radio de 10 km" en límites para cada dimensión de coordenadas, y aprieta los límites a medida que recurre en el árbol.
fuente
Sí, hay una mejor manera. Necesita usar un índice espacial . Estos índices organizan metadatos sobre geometrías para filtrar geometrías lejanas muy rápidamente, ahorrando muchos ciclos de CPU al evitar los cálculos que usted describe. No debería molestarse en implementar uno usted mismo, ya que todas las principales bases de datos relacionales proporcionan un tipo de geometría espacial e índices para acompañarlas.
Lo que desea examinar son consultas "a distancia" (consultas de geometrías dentro de una cierta distancia de alguna otra geometría). Estos son un problema muy estándar y muy resuelto y son posibles en todas las bases de datos anteriores (e integradas en varias):
ST_DWithin
STDistance
(no está claro que el uso del índice en la versión de geografía 3D de esta función sea compatible)SDO_WITHIN_DISTANCE
(Esto no dice explícitamente que activará el uso del índice. Verificaría dos veces el plan de consulta. Es posible que deba aplicar unSDO_FILTER
para que use el índice).Solución alternativa para activar el uso del índice
En el peor de los casos en el que tiene problemas para que el sistema use el índice espacial con estas consultas, puede agregar un filtro adicional. Crearía un cuadro delimitador cuadrado con lados de longitud 2 * (distancia de búsqueda) centrados en su punto de búsqueda y compararía los cuadros delimitadores de las geometrías de la tabla con eso antes de verificar la distancia real. Eso es lo que PostGIS
ST_DWithin
hace arriba internamente de todos modos.Distancia en SIG
Si bien los índices espaciales son fantásticos y absolutamente la solución correcta para su problema, el cálculo de la distancia puede ser lógicamente complicado. En particular, debe preocuparse sobre en qué proyección (básicamente todos los parámetros para el sistema de coordenadas) se almacenan sus datos. La mayoría de las proyecciones 2D (que no sean sistemas de coordenadas angulares como las diversas proyecciones lat / long) distorsionan la longitud significativamente. Por ejemplo, la proyección de Web Mercator (la utilizada por Google, Bing y cualquier otro proveedor de mapas base importante) expande áreas y distancias cada vez más a medida que la ubicación se aleja del ecuador . Podría estar equivocado ya que no tengo educación formal en SIG, pero lo mejor que he visto para proyecciones 2D son algunas específicas que prometen distancias correctas desde unpunto único y constante en todo el mundo. (No, no es práctico usar una proyección diferente para cada consulta; eso haría que sus índices sean inútiles).
La conclusión es que debe asegurarse de que sus cálculos sean precisos. La forma más simple de hacerlo desde una perspectiva de desarrollo es usar proyecciones angulares (a menudo se las denomina "geográficas") y funciones que apoyan hacer las matemáticas usando un modelo de esferoides, pero estos cálculos son un poco más caros que las contrapartes 2D y algunos DB pueden no admitir su indexación. Sin embargo, si puede obtener un rendimiento aceptable al usarlos, ese es probablemente el camino a seguir. Otra opción común son las proyecciones regionales (como las zonas UTM) que consiguen distancias y áreas bastante cercanas para corregir si sus datos se limitan a una parte particular del mundo. Lo mejor para su aplicación dependerá de sus requisitos específicos,
Esto se aplica incluso si no utiliza índices espaciales integrados. Sus datos tienen cierta proyección, independientemente de la tecnología o técnica que esté utilizando o use actualmente en el futuro, y ya está afectando cualquier consulta y cálculo que esté haciendo.
fuente
Estoy de acuerdo en que, de ser posible, utilizar el soporte específico en una base de datos sería la forma más sensata de hacerlo.
Sin embargo, si tuviera que hacer esto en una base de datos sin soporte específico, comenzaría preguntando por un cuadrado que encierra el circuito, por ejemplo (y> (y1 - rad)) AND (y <(y1 + rad)) AND (x> ( x1 - rad)) AND (x <(x1 + rad)). Suponiendo que sus puntos tengan una distribución más o menos uniforme, la consulta de un cuadrado le dará sus coincidencias verdaderas más un 30% de coincidencias falsas adicionales. Luego puede eliminar las coincidencias falsas.
fuente
x
yy
. (Quizás combinado, quizás separado. Perfil un poco para averiguar cuál funciona mejor en la práctica.)BETWEEN
consultas. No veo por qué, en el peor de los casos, no podría tener 2 índices y luego los resultados filtrados de cada índice se unen. (Eso es algo que los RDBMS hacen internamente cuando consideran que vale la pena usar múltiples índices). Si un índice combinado funciona, debería filtrar una dimensión por completo en el primer nivel y luego reducirla relativamente rápido en el segundo nivel.y between -68 and -69 and x between 10 and 11
pero por supuesto, el índice espacial hace un mejor trabajo para esa tarea