Подтвердить что ты не робот

База данных: лучший способ отслеживания данных геоданных?

У меня есть база данных MySQL. Я храню дома в базе данных и выполняю буквально всего 1 запрос к базе данных, , но мне нужно, чтобы этот запрос выполнялся сверхбыстро, и чтобы возвращать все дома в квадратной области геолота широты и долготы.

SELECT * FROM homes 
WHERE geolat BETWEEN ??? AND ???
AND geolng BETWEEN ??? AND ???

Как наилучшим образом я могу хранить свои геоданные, чтобы я мог выполнить этот запрос, чтобы показать все дома в поле геолокации быстрее?

В принципе:

  • Я использую лучший оператор SQL для выполнения этого запроса быстрее?
  • Существует ли какой-либо другой метод, возможно, даже не используя базу данных, чтобы я мог запросить самый быстрый способ получения результатов в домах в границах боковых геолокаций?

В случае, если это помогает, я включил схему таблицы базы данных ниже:

CREATE TABLE IF NOT EXISTS `homes` (
  `home_id` int(10) unsigned NOT NULL auto_increment,
  `address` varchar(128) collate utf8_unicode_ci NOT NULL,
  `city` varchar(64) collate utf8_unicode_ci NOT NULL,
  `state` varchar(2) collate utf8_unicode_ci NOT NULL,
  `zip` mediumint(8) unsigned NOT NULL,
  `price` mediumint(8) unsigned NOT NULL,
  `sqft` smallint(5) unsigned NOT NULL,
  `year_built` smallint(5) unsigned NOT NULL,
  `geolat` decimal(10,6) default NULL,
  `geolng` decimal(10,6) default NULL,
  PRIMARY KEY  (`home_id`),
  KEY `geolat` (`geolat`),
  KEY `geolng` (`geolng`),
) ENGINE=InnoDB  ;

UPDATE

Я понимаю, что пространственный фактор будет влиять на кривизну Земли, но меня больше всего интересует возвращение геоинформационных данных FASTEST. Если эти пакеты пространственных баз данных как-то быстрее не возвращают данные, не рекомендуется использовать пространственные расширения. Благодаря

ОБНОВЛЕНИЕ 2

Обратите внимание: никто не ответил на вопрос. Я очень надеюсь на любую помощь, которую я могу получить. Спасибо заранее.

4b9b3361

Ответ 1

Существует хорошая статья о производительности геолокации MySQL здесь.

РЕДАКТИРОВАТЬ. Довольно уверен, что используется фиксированный радиус. Кроме того, я не на 100% уверен, что алгоритм вычисления расстояния является самым продвинутым (т.е. Будет "сверлить" через Землю).

Что важно, так это то, что алгоритм дешев, чтобы дать вам ограничение на парку на количество строк, чтобы сделать правильный поиск расстояния.

Ответ 3

Если вам действительно нужно идти на производительность, вы можете определить ограничивающие поля для своих данных и сопоставить предварительные вычислительные рамки с вашими объектами при вставке и использовать их позже для запросов.

Если набор результатов достаточно мал, вы все равно можете корректировать точность в логике приложения (проще масштабировать горизонтально, чем базу данных), позволяя при этом получать точные результаты.

Взгляните на Брет Слаткин geobox.py, который содержит отличную документацию для этого подхода.

Я бы порекомендовал проверить PostgreSQL и PostGIS по сравнению с MySQL, если вы планируете делать более сложные запросы в обозримом будущем.

Ответ 4

Вот трюк, который я использовал с некоторым успехом, - создать округлые области. То есть, если у вас есть место, которое находится в 36.12345, -120.54321, и вы хотите сгруппировать его с другими местоположениями, расположенными в полумильной (приблизительной) сетке, вы можете назвать его область 36.12x-120.54 и все остальные местоположения с одинаковым округлением будут попадать в один и тот же блок.

Очевидно, что это не дает вам чистого радиуса, т.е. если местоположение, на которое вы смотрите, ближе к одному краю, чем другое. Однако с такой настройкой достаточно просто вычислить восемь ящиков, которые окружают ваше основное поле. К остроумию:

[36.13x-120.55][36.13x-120.54][36.13x-120.53]
[36.12x-120.55][36.12x-120.54][36.12x-120.53]
[36.11x-120.55][36.11x-120.54][36.11x-120.53]

Потяните все местоположения с соответствующими ярлыками округления, а затем, как только вы их вытащите из базы данных, вы можете выполнить вычисления расстояния, чтобы определить, какие из них использовать.

Ответ 5

Используемые индексы действительно являются индексами B-дерева и поддерживают ключевое слово BETWEEN в вашем запросе. Это означает, что оптимизатор может использовать ваши индексы, чтобы найти дома в вашем "ящике". Однако это не означает, что он всегда будет использовать индексы. Если вы укажете диапазон, содержащий слишком много "хитов", индексы не будут использоваться.

Ответ 6

Это выглядит довольно быстро. Моя единственная забота заключается в том, что он будет использовать индекс, чтобы получить все значения в пределах 3 миль от широты, а затем отфильтровать их для значений в пределах 3 миль от долготы. Если я понимаю, как работает базовая система, вы можете использовать только один индекс для каждой таблицы, поэтому либо индекс на lat, либо долгое время бесполезен.

Если у вас было большое количество данных, это могло бы ускорить процесс, чтобы дать каждому квадрату 1x1 мили уникальный логический идентификатор, а затем сделать дополнительное ограничение на SELECT, которое (area = "23234/34234" OR area = "23235/34234" ИЛИ...) для всех квадратов вокруг вашей точки, а затем заставить базу данных использовать этот индекс, а не lat и long. Тогда вы будете фильтровать гораздо меньше квадратных миль данных.

Ответ 7

Дома? У вас, вероятно, даже не будет десяти тысяч из них. Просто используйте индекс в памяти, например STRTree.

Ответ 8

Придерживаясь вашего текущего подхода, вы должны сделать одно изменение, Вместо индексации геолата и геолонга отдельно вы должны иметь составной индекс:

KEY `geolat_geolng` (`geolat`, `geolng`),

В настоящее время ваш запрос будет использовать только один из двух индексов.

Ответ 10

Возможно, вам стоит создать отдельную таблицу GeoLocations, в которой есть первичный ключ ('geolat', 'geolng') и имеет столбец, который содержит home_id, если у этой конкретной геолокации есть дом. Это должно позволить оптимизатору искать ряд географических местоположений, которые будут отсортированы на диске для списка home_ids. Затем вы можете выполнить соединение со своей таблицей "дома", чтобы найти информацию об этих домашних файлах.

CREATE TABLE IF NOT EXISTS `GeoLocations` (
`geolat` decimal(10,6) NOT NULL,
`geolng` decimal(10,6) NOT NULL,
`home_id` int(10) NULL
PRIMARY KEY  (`geolat`,`geolng`)
);

SELECT GL.home_id
FROM GeoLocations GL
INNER JOIN Homes H
 ON GL.home_id = H.home_id
WHERE GL.geolat between X and Y
 and GL.geolng between X and Y

Ответ 11

Так как MySQL 5.7 mysql может использовать геоиндекс, например ST_Distance_Sphere() и ST_Contains(), которые улучшают производительность.