2011-01-18 2 views
9

Я хочу хранить значения широты и долготы мест в таблице базы данных mysql. Учитывая будущее, я захочу найти эти места в определенном радиусе определенного местоположения. Сказав это, какие типы данных должны хранить значения широты и долготы? Пожалуйста, вы могли бы предоставить мне создать сценарий таблицы для столбцов, как так:Настройка базы данных широты и долготы MySQL

place_id | lat | long 

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

Спасибо за любую помощь.

+0

Возможный дубликат [Какой идеальный тип данных используется при хранении широты/долготы в базе данных MySQL?] (Http://stackoverflow.com/questions/159255/what-is-the-ideal-data-type -to-use-when-storing-latitude-longitudes-in-mysql) – Gajus

ответ

21

Вы должны хранить точки в колонке опалить от типа данных Point, который вы можете индексировать с SPATIAL индекса (если ваш тип таблицы MyISAM):

CREATE SPATIAL INDEX sx_place_location ON place (location) 

SELECT * 
FROM mytable 
WHERE MBRContains 
       (
       LineString 
         (
         Point($x - $radius, $y - $radius), 
         Point($x + $radius, $y + $radius) 
         ) 
       location 
       ) 
     AND Distance(Point($x, $y), location) <= $radius 

Это позволит значительно улучшить скорость запросов, таких как " найти все в пределах заданного радиуса ".

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

Вы по-прежнему можете использовать полярные координаты, но формулы для расчета MBR и расстояния будут более сложными.

+1

Все мои таблицы используют InnoDB, поскольку я использую внешние ключи. Не стоит ли иметь таблицы как в InnoDB, так и в MyISAM? – Martin

+0

@Martin: 'MyISAM' без транзакций, и вы не можете использовать ограничения FOREIGN KEY. Для запросов «SELECT» нет проблем с перемещением таблиц разных типов. – Quassnoi

+0

Да, я понимаю, что внешние ключи не работают в MyISAM, однако, если у меня есть дополнительная таблица для координат, и это, поскольку MyISAM и все мои другие таблицы InnoDB - это не проблема? – Martin

0

Я выкопал несколько часов через тонны тем и не мог найти запрос, возвращая точки в радиусе, определяемом километром. ST_Distance_Sphere делает это, однако, сервер MariaDB 5.5, не поддерживает ST_Distance_Sphere().

Управляемый, чтобы получить что-то работает, так вот мое решение, совместимое с доктриной 2.5 и доктрина CrEOF Spatial библиотека:

$sqlPoint = sprintf('POINT(%f %f)', $lng, $lat); 

    $rsm = new ResultSetMappingBuilder($this->manager); 
    $rsm->addRootEntityFromClassMetadata('ApiBundle\\Entity\\Place', 'p'); 

    $query = $this->manager->createNativeQuery(
     'SELECT p.*, AsBinary(p.location) as location FROM place p ' . 
     'WHERE (6371 * acos(cos(radians(Y(ST_GeomFromText(?)))) ' . 
     '* cos(radians(Y(p.location))) * cos(radians(X(p.location)) ' . 
     '- radians(X(ST_GeomFromText(?)))) + sin(radians(Y(ST_GeomFromText(?)))) * sin(radians(Y(p.location))))) <= ?', 
     $rsm 
    ); 

    $query->setParameter(1, $sqlPoint, 'string'); 
    $query->setParameter(2, $sqlPoint, 'string'); 
    $query->setParameter(3, $sqlPoint, 'string'); 
    $query->setParameter(4, $radius, 'float'); 

    $result = $query->getResult(); 

Предполагая, что LNG и лату является XY неподвижной точки, место является объектом с поле «местоположение» POINT. Я не мог использовать DQL напрямую из-за проблем с привязкой param MySQL, поэтому для низкоуровневого исходного запроса. Rms требуется для сопоставления результатов с объектами сущности. Можно жить без него.

Не стесняйтесь использовать его. Надеюсь, это сэкономит вам время.

Смежные вопросы