У меня есть две таблицы MySQL с местами, table1
а также table2
(увидеть ниже). В каждой таблице более 100 тысяч строк. Я хотел бы найти расстояние между каждым местоположением в этих двух таблицах, используя их геолокации.
Вот запрос MySQL, чтобы найти расстояние между одной геолокацией, например, (-37.22, 88.88) и всеми местоположениями в table1
,
$lat = -37.22;
$long = 88.88;
SELECT id, latitude, longitude, name
((2 * 3960 *
ATAN2(
SQRT(
POWER(SIN((RADIANS($lat - latitude))/2), 2) +
COS(RADIANS(latitude)) *
COS(RADIANS($long)) *
POWER(SIN((RADIANS($long - longitude))/2), 2)
),
SQRT(1-(
POWER(SIN((RADIANS($lat - latitude))/2), 2) +
COS(RADIANS(latitude)) *
COS(RADIANS($long)) *
POWER(SIN((RADIANS($long - longitude))/2), 2)
))
)
)) AS distance FROM table1 ORDER BY distance;
Table1
id name latitude longitude
1 foo1 -37.12 62.34
2 foo2 -47.12 72.34
3 foo3 -57.12 82.34
Table2
id name latitude longitude
1 bar1 -38.22 66.11
2 bar2 -48.22 76.11
3 bar3 -58.22 86.11
Учитывая, что это тоже большие данные, я не уверен, с чего начать. Мысли?
Если вы хотите оптимизировать путешествие или приблизиться к местоположению, вы должны использовать пространственные функции. http://dev.mysql.com/doc/refman/5.7/en/spatial-extensions.html
Но похоже, что вы хотите каждый расчет, так что да, вам нужно будет сделать 10 миллиардов операций.
SIN()
а также COS()
поэтому создайте дополнительное поле для каждой строки с этим значением. Таким образом, вы должны сделать это только один раз, а не 100 000 раз для каждой строкиРЕДАКТИРОВАТЬ:
После прочтения вашего последнего комментария. Вам нужен пространственный индекс. Так же, как при поиске одного идентификатора в вашей базе данных, пространственный индекс оптимизирует поиск поблизости.
Также вы можете сделать поиск коробки. Вместо того, чтобы искать всю вселенную, вы создаете рамку вокруг своей точки и ищите внутри этой рамки. Используя обычный индекс с плавающей точкой, вы делаете что-то вроде этого
SELECT t1.name, t2.name, mysql.Distancefunction(t1,t2) as distance
from t1
cross join t2
WHERE t2.x between (t1.x - 0.001) and (t1.x + 0.001) -- use x float index
and t2.y between (t1.y - 0.001) and (t1.y + 0.001) -- use y float index
and mysql.Distancefunction(t1,t2) < 100 km -- use spatial index
Вы можете играть с дельтой 0,001. Если вы получаете слишком много результатов, вы используете 0,0001. Если вы получаете мало результатов, вы делаете второй шаг с 0,01 только для тех мест без 100 соседей.
Других решений пока нет …