База данных Geonames: получение полной иерархии (страна -> admin1 -> admin2 -> город) с одним единственным запросом mysql - PullRequest
2 голосов
/ 06 сентября 2011

Я пытаюсь использовать базу данных geonames (загруженную и загруженную в локальный MySQL) для получения всей связанной информации из местоположения (самый низкий уровень - название города) с использованием драйверов Java и JDBC.

У меня большая проблема с производительностью: каждый запрос занимает около 4-5 секунд, и мне нужно разделить запрос на три части, чтобы получить все нужные мне результаты.

Я загрузил базу данных allCountries, коды admin1 и admin2. Поскольку уникальные идентификаторы admin1 и admin2 состоят из информации, полученной из запроса по всем странам, мне пришлось сделать что-то подобное для запроса к базе данных:

String query = "SELECT DISTINCT "
             + "loc_geoname.name AS name,"
             + "loc_geoname.asciiname AS asciiname,"
             + "loc_geoname.alternatenames AS alternames,"
             + "loc_geoname.latitude AS latitude,"
             + "loc_geoname.longitude AS longitude,"
             + "loc_geoname.country AS country_code,"
             + "loc_geoname.admin1 AS admin1, "
             + "loc_geoname.admin2 AS admin2, "
             + "loc_countryinfo.name AS country, "
             + "loc_countryinfo.currency AS value "
             + "FROM loc_geoname, loc_countryinfo "
             + "WHERE loc_countryinfo.iso_alpha2=loc_geoname.country "
             + "AND loc_geoname.asciiname IN (" + search + ") "
             + "AND loc_geoname.country='" + countrycode + "' "
             + "AND loc_geoname.fcode like 'PP%' limit 10;"

и это запрос, который я использую, чтобы получить всю информацию для города (поиск и код страны - это предварительно созданные строки, они не важны)

Теперь, чтобы получить имя admin1 и имя admin2, мне нужно запустить два новых запроса:

String a1 = res.getString("admin1");
String query_area = "select name from loc_admin1Codes where code='" + countrycode + "." + a1 + "';";

String a2 = res.getString("admin2");
String query_district = "select name from loc_admin2Codes where code='" + countrycode + "." + a1 + "." + a2 + "';";

Я уверен, что можно объединить два запроса в один (но не уверен), но я не знаю, как создавать коды admin1 и admin2 без получения значений из первого запроса и объединения строк во второй и третий.

Кроме того, я уверен, что могу улучшить свой первый запрос, чтобы немного ускорить его (возможно, используя объединения вместо перекрестной комбинации с предложением where ...)

Структура таблицы такая же, как определено здесь , и я ничего от этого не изменил. Заранее всем спасибо за подсказки!

1 Ответ

4 голосов
/ 06 сентября 2011

Вы не должны запрашивать его каждый раз.

Я сделал это, добавив столбцы "admin1Nameé и" admin2Name ", и обновил их значение простым SQL-запросом.

Эта база данныхочень большой, поэтому вы должны подумать о вычисляемом столбце.

РЕДАКТИРОВАТЬ: если вы все еще хотите делать это каждый раз

SELECT 
    locgeoname.*, 
    loc_countryinfo.name, loc_admin1Codes.name, loc_admin2Codes.name, 
FROM 
    loc_geoname 
INNER JOIN 
    loc_countryinfo ON loc_countryinfo.iso_alpha2 = loc_geoname.country
INNER JOIN 
    loc_admin1Codes ON code = loc_countryinfo.iso_alpha2 + '.' + admin1  
INNER JOIN 
    loc_admin2Codes ON code = loc_countryinfo.iso_alpha2 + '.' + admin1 + '.' + admin2
...