Я работаю над поисковой системой, которая должна определить, включена ли начальная и конечная точка (около 50 км) маршрута. У меня много маршрутов, хранящихся в DB mysql, в виде точек [300k строк].Начало и конец маршрута в 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]
... ... ... ...
Вопрос в том, как наиболее effectivelly выбрать только маршруты (route_id), на котором (или около 50 км) начальную и конечную точки является?
Я попытался объединить [в примере] (или внутреннее соединение), который работает, но запрос занимает около 0.4s, что слишком много. Любая идея, как оптимизировать?
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:
я сделал оптимизации на основе @Djeramon советы ANO Теперь 0.06s Я не знаю, что это лучшее, что я могу достичь, и что делать, если у меня будет 50M строки:)
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;
Вы пытались использовать подзапрос существует или просто с условием «и»? Союз будет использоваться для или условия. Другим решением может быть сохранение 50-километрового конверта в индексированном вычисленном поле (если вы можете создать пространственный индекс в вычисленном поле) и запустить запрос по этому вопросу. – Shadow
Хм, у меня нет идеи, как реализовать свои рекомендации, чтобы получить тот же результат. – rossinelo