Ich versuche, mit einem Geosuchprojekt zu beginnen, das alle Orientierungspunkte in den 10 km / Meilen (für diese Geschichte nicht wichtig) eines bestimmten Orientierungspunkts findet.
Nehmen wir zum Beispiel an, ich habe eine Datenbank mit 1.000.000 Sehenswürdigkeiten. Um alle Orientierungspunkte im 10-Meilen-Bereich eines Orientierungspunkts mit bestimmten Koordinaten zu finden, müsste ich eine Entfernung zwischen einem Orientierungspunkt aus meiner Suche und 1.000.000 Orientierungspunkten berechnen.
Gibt es einen besseren Weg, das zu tun?
Als Alternative habe ich gedacht, Sehenswürdigkeiten wie Land, Region, Stadt, Nachbarschaft, Geschäft, Historie usw. so zu kategorisieren, dass das Geschäft Teil einer Nachbarschaft oder Stadt sein kann. Stadt ist ein Teil einer Region, eines Landes usw. Dies kann eine Liste von Berechnungen einschränken, aber es sieht nach viel Arbeit aus, um eine schnelle und genaue Suche zu ermöglichen.
Könnte das Google Maps API helfen?
quelle
Antworten:
Seit SQL Server 2008 gibt es einen geografischen Datentyp, der Standorte (Lat / Lon-Paare) speichert und das Schreiben standortbezogener Abfragen erleichtert.
Es gibt eine vorhandene StackOverflow-Antwort, die diese eingehende Beschreibung enthält.
Eine grundlegende Abfrage, um die nächsten 7 Elemente zu finden :
Eine grundlegende Abfrage, um alles innerhalb von 100 m zu finden (zweite Antwort auf die Frage)
quelle
Verwenden Sie eine Datenbank mit Unterstützung für GIS- Abfragen (Geoinformationssysteme) . Die meisten Datenbanken unterstützen dies direkt oder haben Erweiterungen, aber die Details sind datenbankspezifisch (in ihrer Antwort) zeigt Flater die Syntax für SQL Server).
Wenn Sie solche Abfragen in Ihrer Anwendung implementieren müssen, können Sie eine Datenstruktur implementieren, die räumliche Abfragen ermöglicht, z . B. einen kd-Baum . Dies ähnelt einem binären Suchbaum, mit der Ausnahme, dass jede Ebene der Baumpartitionen auf einer anderen Koordinatendimension liegt. Auf diese Weise können Sie die Suche auf eine kleinere Anzahl möglicher Kandidaten beschränken. Tatsächlich übersetzen Sie Ihre Suche "10 km Radius" in Grenzen für jede Koordinatendimension und ziehen die Grenzen fester, wenn Sie in den Baum zurückkehren.
quelle
Ja, es gibt einen besseren Weg. Sie müssen einen räumlichen Index verwenden . Diese Indizes organisieren Metadaten zu Geometrien, um weit entfernte Geometrien sehr schnell herauszufiltern. Dadurch werden viele CPU-Zyklen gespart, indem die von Ihnen beschriebenen Berechnungen vermieden werden. Sie sollten sich nicht die Mühe machen, eine selbst zu implementieren, da alle wichtigen relationalen Datenbanken einen räumlichen Geometrietyp und dazugehörige Indizes bereitstellen.
Was Sie untersuchen möchten, sind Abfragen "innerhalb der Entfernung" (Abfragen für Geometrien innerhalb einer bestimmten Entfernung von einer anderen Geometrie). Dies sind sehr standardmäßige und weitgehend gelöste Probleme, die in allen oben genannten Datenbanken (und in mehreren integriert) möglich sind:
ST_DWithin
STDistance
(Es ist nicht klar, ob die Indexverwendung in der 3D-Geografie-Version dieser Funktion unterstützt wird.)SDO_WITHIN_DISTANCE
(Dies bedeutet nicht explizit, dass die Verwendung des Index ausgelöst wird. Ich würde den Abfrageplan noch einmal überprüfen. Möglicherweise müssen Sie einen anwendenSDO_FILTER
, damit er den Index verwendet.)Problemumgehung zum Auslösen der Indexverwendung
Im schlimmsten Fall, wenn Sie Probleme haben, das System dazu zu bringen, den räumlichen Index mit diesen Abfragen zu verwenden, können Sie einen zusätzlichen Filter hinzufügen. Sie erstellen einen quadratischen Begrenzungsrahmen mit Seiten der Länge 2 * (Suchabstand), der an Ihrem Suchpunkt zentriert ist, und vergleichen die Begrenzungsrahmen der Tabellengeometrien damit , bevor Sie den tatsächlichen Abstand überprüfen. Das macht PostGIS '
ST_DWithin
oben sowieso intern.Entfernung in GIS
Während räumliche Indizes fantastisch und absolut die richtige Lösung für Ihr Problem sind, kann die Entfernungsberechnung logisch kompliziert werden. Insbesondere müssen Sie sich Gedanken darüber machen, in welcher Projektion (im Grunde alle Parameter für das Koordinatensystem) Ihre Daten gespeichert sind. Die meisten 2D-Projektionen (andere als Winkelkoordinatensysteme wie die verschiedenen Lat / Long-Projektionen) verzerren die Länge erheblich. Beispielsweise erweitert die Web Mercator-Projektion (die von Google, Bing und allen anderen großen Anbietern von Basiskarten verwendet wird) Bereiche und Entfernungen zunehmend, je weiter der Standort vom Äquator entfernt ist . Ich kann mich irren, da ich nicht offiziell in GIS ausgebildet bin, aber das Beste, was ich für 2D-Projektionen gesehen habe, sind einige spezifische, die korrekte Abstände von a versprecheneinzelner, konstanter Punkt in der ganzen Welt. (Nein, es ist nicht praktisch, für jede Abfrage eine andere Projektion zu verwenden. Dadurch werden Ihre Indizes unbrauchbar.)
Die Quintessenz ist, dass Sie sicherstellen müssen, dass Ihre Mathematik korrekt ist. Aus Sicht der Entwicklung ist dies am einfachsten, wenn Sie Winkelprojektionen (diese werden häufig als "geografisch" bezeichnet) und Funktionen verwenden, die das Berechnen mit einem Sphäroidmodell unterstützen. Diese Berechnungen sind jedoch etwas teurer als die 2D-Berechnungen und einige DBs unterstützen die Indizierung möglicherweise nicht. Wenn Sie mit ihnen jedoch eine akzeptable Leistung erzielen können, ist dies wahrscheinlich der richtige Weg. Eine weitere häufig verwendete Option sind regionale Projektionen (wie UTM-Zonen), mit denen Entfernungen und Bereiche nahezu korrigiert werden, wenn Ihre Daten auf einen bestimmten Teil der Welt beschränkt sind. Was für Ihre App am besten ist, hängt von Ihren spezifischen Anforderungen ab.
Dies gilt auch dann, wenn Sie keine integrierten räumlichen Indizes verwenden. Ihre Daten haben eine gewisse Projektion, unabhängig davon, welche Technologie oder Technik Sie derzeit verwenden oder in Zukunft verwenden. Sie wirken sich bereits auf alle Abfragen und Berechnungen aus, die Sie durchführen.
quelle
Ich würde zustimmen, dass die Verwendung von spezifischem Support in einer Datenbank, wenn möglich, der sinnvollste Weg ist, dies zu tun.
Wenn ich dies jedoch in einer Datenbank ohne spezielle Unterstützung tun müsste, würde ich zunächst nach einem Quadrat suchen, das den Zirkel einschließt, z. B. (y> (y1 - rad)) AND (y <(y1 + rad)) AND (x> ( x1 - rad)) AND (x <(x1 + rad)). Unter der Annahme, dass Ihre Punkte ungefähr gleichmäßig verteilt sind und Sie nach einem Quadrat suchen, erhalten Sie Ihre wahren Übereinstimmungen plus etwa 30% zusätzliche falsche Übereinstimmungen. Sie können dann die falschen Übereinstimmungen löschen.
quelle
x
und optimiert werdeny
. (Vielleicht kombiniert, vielleicht getrennt. Ich möchte ein wenig herausfinden, was in der Praxis besser funktioniert.)BETWEEN
Abfragen verwendet werden. Ich verstehe nicht, warum Sie im schlimmsten Fall nicht zwei Indizes haben konnten und die gefilterten Ergebnisse aus jedem Index dann zusammengeführt werden. (Dies tun RDBMS intern, wenn sie die Verwendung mehrerer Indizes für sinnvoll erachten.) Wenn ein kombinierter Index funktioniert, sollte er eine Dimension auf der ersten Ebene vollständig herausfiltern und auf der zweiten Ebene relativ schnell eingrenzen.y between -68 and -69 and x between 10 and 11
aber natürlich räumliche Index einen besseren Job für diese Aufgabe