使用包含具有1.7M UK邮政编码的表的MariaDB数据库,我试图确定给定纬度和经度集的最近邮政编码,如下所示:
MariaDB [dev]> SELECT COUNT(*) as total, postcode, ( 3959 * acos( cos( radians( 53.18526 ) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(-3.01984) ) + sin( radians(53.18526) ) * sin( radians( latitude ) ) ) ) AS distance FROM uk_postcodes LIMIT 1;
+---------+----------+--------------------+
| total | postcode | distance |
+---------+----------+--------------------+
| 1751331 | AB10 1AA | 276.23821854757585 |
+---------+----------+--------------------+
1 row in set (0.35 sec)
出于本示例的目的,我添加了COUNT(*)
来显示表中要开始的记录数。折扣COUNT(*)
会导致查询在0.01秒内执行。
我需要获取最近的邮政编码,所以我添加ORDER BY
语句:
MariaDB [dev]> SELECT postcode, ( 3959 * acos( cos( radians( 53.18526 ) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(-3.01984) ) + sin( radians(53.18526) ) * sin( radians( latitude ) ) ) ) AS distance FROM uk_postcodes ORDER BY distance LIMIT 1;
+----------+---------------------+
| postcode | distance |
+----------+---------------------+
| CH5 3PF | 0.13513453795504218 |
+----------+---------------------+
1 row in set (2.33 sec)
返回正确的结果,但需要很长时间。
Google地理编码API能够立即返回最近的邮政编码:https://maps.googleapis.com/maps/api/geocode/json?latlng=53.18526,-3.01984
如何立即从我的数据库返回结果?
答案 0 :(得分:0)
以上是我在sql代码中的注释中的建议,以防它稍微提高了性能:
SELECT postcode
, min(( 3959 * acos( cos( radians( 53.18526 ) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(-3.01984) ) + sin( radians(53.18526) ) * sin( radians( latitude ) ) ) )) AS distance
FROM uk_postcodes GROUP BY postcode;
答案 1 :(得分:0)
我设法解决了性能问题!
+-------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+-------+
| postcode | varchar(8) | NO | PRI | NULL | |
| district | varchar(4) | YES | | NULL | |
| postal_town | varchar(35) | YES | MUL | NULL | |
| county | varchar(37) | YES | | NULL | |
| country | varchar(16) | YES | | NULL | |
| easting | int(11) | YES | | NULL | |
| northing | int(11) | YES | | NULL | |
| latitude | decimal(7,5) | YES | | NULL | |
| longitude | decimal(7,5) | YES | | NULL | |
| type | varchar(14) | YES | | NULL | |
| id | varchar(32) | YES | | NULL | |
| latlng | geometry | NO | MUL | NULL | |
+-------------+--------------+------+-----+---------+-------+
latlng字段具有空间索引,并已填充如下:
UPDATE uk_postcodes SET latlng = GeomFromText(CONCAT('POINT(',latitude,' ', longitude, ')'));
SELECT postcode, ( 3959 * acos( cos( radians( 53.18526 ) ) * cos( radians( X(latlng) ) ) * cos( radians( Y(latlng) ) - radians(-3.01984) ) + sin( radians(53.18526) ) * sin( radians( X(latlng) ) ) ) ) AS distance
FROM uk_postcodes
WHERE MBRContains
(LineString
(
Point (53.18526 + 10 / (111.1 / COS(RADIANS(53.18526))), -3.01984 + 10 / 111.1),
Point (53.18526 - 10 / (111.1 / COS(RADIANS(53.18526))), -3.01984 - 10 / 111.1)
),
latlng
)
ORDER BY distance
LIMIT 1;
+----------+---------------------+
| postcode | distance |
+----------+---------------------+
| CH5 3PF | 0.13513453795504218 |
+----------+---------------------+
1 row in set (0.00 sec)