2016-08-24 8 views
1

Ich erstelle eine Datenbank, die auf einem MS SQL 2012-Server gehostet wird. Die Hauptfunktion dieser Datenbank besteht darin, Ergebnisse zurückzugeben, die sich in einer bestimmten Entfernung von einem Ursprung befinden. Standorte werden als Breiten-/Längengrad gespeichert.Optimieren von SQL WHERE zum Berechnen der Entfernung zwischen Längen- und Breitenpositionen

Indem ich hier auf Stack Overflow gelesen habe, habe ich eine sehr gute Möglichkeit gefunden, die Datenbank genau nach dem zu durchsuchen, wonach ich suche, und es funktioniert wie ein Zauber! Ich denke jedoch über einen möglichen Weg nach, dies zu optimieren.

Original-SQL-Abfrage

DECLARE @orig_lat DECIMAL(12, 9) 
DECLARE @orig_lng DECIMAL(12, 9) 

SET @orig_lat=56.xxxxxx 
SET @orig_lng=14.xxxxxx 

DECLARE @orig geography = geography::Point(@orig_lat, @orig_lng, 4326); 

SELECT * 
FROM foobar 
WHERE @orig.STDistance(geography::Point(foobar.latitude, foobar.longitude, 4326)) < 2000 

Meine Vermutung ist, dass diese Abfrage hat eine lineare Suche der foobar Tabelle nur die passenden Spalten zurück. Da diese Tabelle jedoch Positionen auf der ganzen Welt enthält, möchte ich wissen, ob ich der Datenbank helfen kann, indem ich die Anzahl der Zeilen reduziere, auf denen die Entfernungsberechnung ausgeführt werden soll. Meine Vermutung ist, dass diese Berechnung für den Server schwer ist.

Ich weiß, woher die Anfrage stammt, und ich weiß auch, dass die maximale Entfernung zwischen den Punkten niemals größer als etwa 100km sein wird.

Hypothese

Da ich weiß, dass ich bis zu 100 km von Entstehungsort nicht nur die ganze Welt suchen muss ich auf die WHERE-Anweisung verbessern, wie unten zu sehen. Durch Erstellen einer Mindest- und Höchstgrenze für den Breiten- und Längengrad, die durch Verschieben der Position um eine Zahl in jeder Richtung erreicht wird.

ich erklären:

  • Herkunft Breite 56.xxxxxx
  • Min Breite 55.xxxxxx
  • Max Breite 57.xxxxxx

  • Herkunft Länge 14.xxxxxx

  • Min Längengrad 13.xxxxxx
  • Max Längengrad 15.xxxx xx

Dadurch erstelle ich eine Zone um den Ursprung, die ungefähr 126km erreicht. Indem ich dies der WHERE-Anweisung hinzufüge, stelle ich zuerst sicher, dass die angeforderte Position innerhalb der korrekten Grenzen liegt. Danach führe ich die Entfernungsberechnung durch, um die exakte Entfernung zu erhalten. Die Entfernungsberechnung wird jetzt nur noch gegen die Zeilen ausgeführt, die innerhalb der Min- und Max-Grenzen statt der ganzen Welt liegen.

Optimierungsvorschlag

DECLARE @orig_lat DECIMAL(12, 9) 
DECLARE @orig_lng DECIMAL(12, 9) 
DECLARE @orig_latMin DECIMAL(12, 9) 
DECLARE @orig_latMax DECIMAL(12, 9) 
DECLARE @orig_lngMin DECIMAL(12, 9) 
DECLARE @orig_lngMax DECIMAL(12, 9) 

SET @orig_lat=56.xxxxxx 
SET @orig_lng=14.xxxxxx 
SET @orig_latMin=55.xxxxxx 
SET @orig_latMax=57.xxxxxx 
SET @orig_lngMin=13.xxxxxx 
SET @orig_lngMax=15.xxxxxx 

DECLARE @orig geography = geography::Point(@orig_lat, @orig_lng, 4326); 

SELECT * 
FROM foobar 
WHERE ([latitude] > @orig_latMin 
    AND [latitude] < @orig_latMax 
    AND [longitude] > @orig_lngMin 
    AND [longitude] < @orig_lngMax) 
    AND @orig.STDistance(geography::Point(foobar.latitude, foobar.longitude, 4326)) < 2000 

Ich weiß Details nicht Datenbank-Implementierung aber bedeutet dies die Abfrage verbessern oder sie es nicht noch schlimmer machen? Meine Vermutung ist, dass es darauf ankommt, wie die WHERE-Anweisung tatsächlich funktioniert und in welcher Reihenfolge sie Dinge dosiert. Meine Hoffnung ist, dass die Grenzkontrollen vor der Abstandsberechnung ausgeführt werden, um die Zeit zu reduzieren, die eine Abstandsberechnung durchgeführt wird.

EDIT

implementiert einfach den vorgeschlagenen Index Vorschlag mit den folgenden Ergebnissen.

ohne Indizierung:

  • Mit optimierten Aussage haben Kosten in Höhe von 0,025352

  • Ohne optimierte Aussage haben Kosten in Höhe von 0,025323

Mit Indexierung:

  • Mit optimierten Aussage haben Kosten in Höhe von 0,0104057

  • Ohne optimierte Aussage haben Kosten in Höhe von 0,0253234

+0

Überprüfen Sie den Ausführungsplan –

Antwort

1

Eine gute Faustregel besagt, dass die Ausführungszeit einer Datenbankabfrage von der Anzahl der Plattenseiten abhängt, die gelesen werden müssen. Die CPU-Zeit kann normalerweise ignoriert werden.

Gemäß dieser Regel verbessert die vorgeschlagene Optimierung die Ausführungszeit, wenn sich die Anzahl der Festplattenseiten ändert. Dies ist der Fall, wenn es einen Index auf Breitengrad und Längengrad gibt, mit dem viele Tabellenzeilen und damit viele Plattenseiten übersprungen werden können. Wenn dies der Fall ist, wird der Optimierer sicherlich den Teil der WHERE-Klausel vor der Entfernung berechnen.

Wenn es keinen Index gibt, der mit diesen zwei Spalten hilft, bezweifle ich, dass Sie einen großen Unterschied sehen werden.

+0

Wenn ich Sie richtig verstehe. Durch Bearbeiten der Foobar-Tabelle und Hinzufügen eines solchen Indexes. 'CREATE INDEX index_position auf foobar (Breite, Länge);' Es sollte die Abfrage verbessern? – Carl

+0

Wenn Sie für diese Spalten noch keinen Index haben, fügen Sie einen hinzu und probieren Sie ihn aus. Überprüfen Sie den Ausführungsplan, um sicherzustellen, dass sie wirklich verwendet werden. – Codo

+0

BTW: Ich bin kein Spezialist in Bezug auf SQLServers räumliche Datenunterstützung.Sie sollten jedoch in der Lage sein, den Speicherort in einer Spalte * geography * zu speichern, dann einen räumlichen Index für diese Spalte zu erstellen und optimierte Abfragen darauf auszuführen (ohne das Begrenzungsrechteck für die Entfernung berechnen zu müssen). – Codo

0

Sie können die Abfragezeit mit MS-Management analysieren Studio, führen Sie eine große Abfrage mit Differents Where's aus, es zeigt Ihnen sogar an, welcher Teil der Abfrage welche Zeit benötigt.

können Sie CTRL klicken + L: Anzeige geschätzten executionplan oder STRG + M: tatsächlichen Ausführungsplan angezeigt werden (wenn Sie es ausführen)

Run es einmal mit den „Grenzen“ zuerst, dann wieder mit den Grenzen nach. Sie können sehen, welche langsamer ist, dann versuchen Sie es erneut ohne die Grenzen.

Wenn Sie nicht genügend Daten haben, ist der Unterschied möglicherweise nicht sichtbar.

Verwandte Themen