Ich arbeite an einem Suchsystem, das erkennen sollte, ob Start- und Endpunkt auf (in der Nähe von 50 km) der Route ist. Ich habe viele Routen in Mysql DB als Punkte [300k Zeilen] gespeichert.Start und Ende auf (in der Nähe) der Route in Mysql
Structure
id [primary] | id_route | id_point | lat_lng_point (spatial index)
1 1 1 [GEOMETRY - 25 B]
2 1 2 [GEOMETRY - 25 B]
3 1 3 [GEOMETRY - 25 B]
4 1 4 [GEOMETRY - 25 B]
5 2 1 [GEOMETRY - 25 B]
6 2 2 [GEOMETRY - 25 B]
... ... ... ...
Frage ist, wie die meisten effectivelly nur Routen wählen (route_id), auf dem (oder in der Nähe von 50 km) der Start- und Endpunkte sind?
Ich habe Union versucht [in Beispiel] (oder inneren Join), die funktioniert, aber die Abfrage dauert um 0.4s, die zu viel ist. Irgendeine Idee, wie man optimiert?
SELECT * FROM
(
(
SELECT DISTINCT(id_route)
FROM route_path2
WHERE ST_Contains(ST_MakeEnvelope(
Point(($lng_start+(50/111)), ($lat_start+(50/111))),
Point(($lng_start-(50/111)), ($lat_start-(50/111)))
), route_path2.lat_lng_point)
)
UNION ALL
(
SELECT DISTINCT(id_route)
FROM route_path2
WHERE ST_Contains(ST_MakeEnvelope(
Point(($lng_end+(50/111)), ($lat_end+(50/111))),
Point(($lng_end-(50/111)), ($lat_end-(50/111)))
), route_path2.lat_lng_point)
)
) AS t GROUP BY id_route HAVING count(*) >= 2
EDIT:
Ich habe Optimierung basierend auf @Djeramon Beratung ano jetzt 0.06s Ich weiß nicht, das ist das beste, was ich erreichen kann, und was ist, wenn ich 50M Reihen haben:)
CREATE TEMPORARY TABLE starts_on_route AS
SELECT DISTINCT id_route
FROM route_path2
WHERE ST_Contains(ST_MakeEnvelope(
Point((17.1077+(50/111)), (48.1486+(50/111))),
Point((17.1077-(50/111)), (48.1486-(50/111)))
), route_path2.lat_lng_point);
CREATE INDEX starts_on_route_inx ON starts_on_route(id_route);
SELECT DISTINCT route_path2.id_route
FROM route_path2
LEFT JOIN starts_on_route
ON route_path2.id_route = starts_on_route.id_route
WHERE ST_Contains(ST_MakeEnvelope(
Point((18.7408+(50/111)), (49.2194+(50/111))),
Point((18.7408-(50/111)), (49.2194-(50/111)))
), lat_lng_point)
AND route_path2.id_route = starts_on_route.id_route;
Haben Sie versucht mit einer Existenz Unterabfrage oder nur mit einem einfachen 'und' Bedingung? Union würde für eine oder Bedingung verwendet werden. Eine andere Lösung könnte darin bestehen, den 50 km-Umschlag in einem indizierten berechneten Feld zu speichern (wenn Sie einen räumlichen Index für ein berechnetes Feld erstellen können) und die Abfrage darauf auszuführen. – Shadow
Hmm, ich habe keine Idee, wie Sie Ihre Empfehlungen umsetzen, um das gleiche Ergebnis zu erhalten. – rossinelo