У меня есть база данных, используемая для простого обратного геокодирования. База данных опирается на таблицу, содержащую широту, долготу и название места. Каждый раз, когда пара широта, долгота отсутствует или, лучше, каждый раз, когда искомая широта, долгота слишком сильно отличается от существующей широты, долготы, я добавляю новую строку, используя сервис обратного геокодирования GoogleMaps. Ниже код для создания таблицы адресов:
CREATE TABLE `data_addresses` (
`ID` int(11) NOT NULL COMMENT 'Primary Key',
`LAT` int(11) NOT NULL COMMENT 'Latitude x 10000',
`LNG` int(11) NOT NULL COMMENT 'Longitude x 10000',
`ADDRESS` varchar(128) NOT NULL COMMENT 'Reverse Geocoded Street Address'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `data_addresses`
ADD PRIMARY KEY (`ID`),
ADD UNIQUE KEY `IDX_ADDRESS_UNIQUE_LATLNG` (`LAT`,`LNG`),
ADD KEY `IDX_ADDRESS_LAT` (`LAT`),
ADD KEY `IDX_ADDRESS_LNG` (`LNG`);
ALTER TABLE `data_addresses`
MODIFY `ID` int(11) NOT NULL AUTO_INCREMENT COMMENT 'Primary Key';
Как видите, хитрость заключается в том, чтобы использовать два индекса для широты и долготы. Поскольку обычно широта и долгота являются плавающими, мы используем их значение, умноженное на 10000, поэтому каждая пара широта/долгота уникальна. Это подразумевает разрешение около 50 м, которое удовлетворяет мои потребности.
Теперь проблема: каждый раз, когда мне нужно знать, присутствует ли заданная широта/долгота (MyLat, MyLon) или нет, я выполняю следующий запрос:
SELECT `id`, ROUND(SQRT(POW(ABS(`LAT`-ROUND(MyLat*10000)),2)+POW(ABS(`LNG`-ROUND(MyLon*10000)),2))) AS R FROM splc_smarttrk.`data_addresses` ORDER BY R ASC LIMIT 1
Этот запрос вернет мне ближайшую точку и также даст мне R (рейтинг): меньшее R означает самое близкое приближение, поэтому допустим, что каждый раз, когда я нахожу R, превышающее 10, мне нужно добавить новую строку в таблицу адресов. Таблица адресов в настоящее время содержит около 615 тыс. строк.
Проблема в том, что, несмотря на индексы, которые я разместил, этот запрос слишком медленный (занимает около 2 секунд на сервере с 2x Xeon). Ниже результаты объяснения: