用于获取地理位置记录的 MySQL 查询优化
Posted
技术标签:
【中文标题】用于获取地理位置记录的 MySQL 查询优化【英文标题】:MySQL Query optimisation for fetching geolocation records 【发布时间】:2013-12-09 12:07:24 【问题描述】:我有一个地方的地理位置意味着我有一个CenterLatitude
和CenterLongitude
和一个radius
。在这个半径内有很多不同类型的区域记录RegionType
。我想通过匹配radius
中每个RegionType
的记录强度来获取正确的RegionType
记录。
我目前的逻辑是这样的,
第 1 步:找到最小和最大 lat 和 long 值
$milesToKM = 112.654; $minLat = $data['lat'] - ($data['rad'] / $milesToKM); $maxLat = $data['lat'] + ($data['rad'] / $milesToKM); $minLong = $data['lon'] - ($data['rad'] / $milesToKM); $maxLong = $data['lon'] + ($data['rad'] / $milesToKM);第 2 步:选择 Regiontype
和 count
$query = $pdo->prepare("SELECT `RegionType`, count(`RegionType`) as count from (SELECT RegionType FROM data_api_region WHERE (CenterLatitude between $minLat and $maxLat) AND (CenterLongitude between $minLong and $maxLong) AND languageCode = '" . $data['locale'] . "') q GROUP BY `RegionType`");
$query->execute();
$regionCounts = $query->fetchAll(PDO::FETCH_ASSOC);
unset($query);
$finalCountArr = array();
foreach ($regionCounts as $regionCountData)
$finalCountArr[$regionCountData['RegionType']] = $regionCountData['count'];
第三步:决定相关RegionType
switch (true)
case (isset($finalCountArr['Continent']) && $finalCountArr['Continent'] > 5):
$regionTypeFinal = 'Continent';
break;
case (isset($finalCountArr['Country']) && $finalCountArr['Country'] > 5):
$regionTypeFinal = 'Country';
break;
case (isset($finalCountArr['Multi-Region (within a country)']) && $finalCountArr['Multi-Region (within a country)'] > 5):
$regionTypeFinal = 'Multi-Region (within a country)';
break;
case (isset($finalCountArr['Province (State)']) && $finalCountArr['Province (State)'] > 5):
$regionTypeFinal = 'Province (State)';
break;
case (isset($finalCountArr['Multi-City (Vicinity)']) && $finalCountArr['Multi-City (Vicinity)'] > 5):
$regionTypeFinal = 'Multi-City (Vicinity)';
break;
case (isset($finalCountArr['City']) && $finalCountArr['City'] > 5):
$regionTypeFinal = 'City';
break;
case (isset($finalCountArr['Neighborhood']) && $finalCountArr['Neighborhood'] > 5):
$regionTypeFinal = 'Neighborhood';
break;
default:
$regionTypeFinal = 'Point of Interest';
break;
第 4 步:获取正确的记录
$query = $pdo->prepare("SELECT `id` as regionId, `RegionName` as regionName,`RegionNameLong` as regionNameLong, `RegionType` as regionType,`CenterLongitude` as centerLongitude, `CenterLatitude` as centerLatitude ,`LanguageCode` as languageCode FROM data_api_region WHERE (CenterLatitude between $minLat and $maxLat) AND (CenterLongitude between $minLong and $maxLong) AND languageCode = '" . $data['locale'] . "' AND RegionType = '$regionTypeFinal'");
$query->execute();
$finalResultRegions = $query->fetchAll(PDO::FETCH_ASSOC);
谁能告诉我如何优化这个过程,因为表中缺少记录,所以这个过程需要时间..是否可以使用一个 SQL 查询?
【问题讨论】:
【参考方案1】:没有测试数据或表格布局,所以我无法真正测试它,但它可能可以在一条 SQL 中完成,如下所示:-
SELECT `id` as regionId, `RegionName` as regionName,`RegionNameLong` as regionNameLong, `RegionType` as regionType,`CenterLongitude` as centerLongitude, `CenterLatitude` as centerLatitude ,`LanguageCode` as languageCode
FROM data_api_region
INNER JOIN
(
SELECT CASE
WHEN RegionType = 'Continent' AND `count` > 5
THEN 'Continent'
WHEN RegionType = 'Country' AND `count` > 5
THEN 'Country'
WHEN RegionType = 'Multi-Region (within a country)' AND `count` > 5
THEN 'Multi-Region (within a country)'
WHEN RegionType = 'Province (State)' AND `count` > 5
THEN 'Province (State)'
WHEN RegionType = 'Multi-City (Vicinity)' AND `count` > 5
THEN 'Multi-City (Vicinity)'
WHEN RegionType = 'City' AND `count` > 5
THEN 'City'
WHEN RegionType = 'Neighborhood' AND `count` > 5
THEN 'Neighborhood'
ELSE 'Point of Interest'
END AS regionTypeFinal
FROM
(
SELECT `RegionType`, count(`RegionType`) as `count`
FROM data_api_region
WHERE (CenterLatitude between $minLat and $maxLat)
AND (CenterLongitude between $minLong and $maxLong) AND languageCode = '" . $data['locale'] . "'
GROUP BY `RegionType`
) q
) Sub1
ON data_api_region.RegionType = Sub1.regionTypeFinal
WHERE (CenterLatitude between $minLat and $maxLat)
AND (CenterLongitude between $minLong and $maxLong)
AND languageCode = '" . $data['locale'] . "'
【讨论】:
它确实有效..但是查询仍然需要 2-3 秒才能执行..无论如何谢谢。 你能发布表格声明吗?以上是关于用于获取地理位置记录的 MySQL 查询优化的主要内容,如果未能解决你的问题,请参考以下文章