MariaDB - Geocode查询速度很慢

时间:2016-07-27 10:11:20

标签: mysql google-maps

我正在使用MariaDB 10.1.16,我有一个包含170万英国邮政编码的表格,用于位置自动完成,地理编码和反向地理编码。

下面是表格结构:

return
(from x in dbcontext.table1
    where Age == null || x.age==Age
     && Gender == null || x.gender == Gender
    select new model{
     model properties here..
    }).ToList();

查询表中的单个邮政编码会立即返回结果:

+-------------+--------------+------+-----+---------+-------+
| Field       | Type         | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+-------+
| postcode    | varchar(8)   | NO   | PRI | NULL    |       |
| district    | varchar(4)   | YES  |     | NULL    |       |
| postal_town | varchar(35)  | YES  |     | 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    |       |
+-------------+--------------+------+-----+---------+-------+

但是我现在想用我当前的位置找到最近的邮政编码。

我的大概位置是:MariaDB [dev]> SELECT * FROM uk_postcodes WHERE postcode = "CH5 3NS"; +----------+----------+-------------+--------+---------+---------+----------+----------+-----------+------------+----------------------------------+ | postcode | district | postal_town | county | country | easting | northing | latitude | longitude | type | id | +----------+----------+-------------+--------+---------+---------+----------+----------+-----------+------------+----------------------------------+ | CH5 3NS | CH5 | Hawarden | Clwyd | Wales | 331718 | 365725 | 53.18422 | -3.02325 | Geographic | f99a64139bfb8cf8091ca870808b355b | +----------+----------+-------------+--------+---------+---------+----------+----------+-----------+------------+----------------------------------+ 1 row in set (0.00 sec)

我的查询:

53.1852582, -3.0198408999999997

虽然结果是正确的,但是花了太长时间。但为什么呢?

2 个答案:

答案 0 :(得分:0)

这个答案不太清楚为什么它如此慢(在订购之前计算数据库中每一行的值),但可能是一个快速的黑客来减少要检查的行数:

当您将纬度/经度值限制为附近的值时,您可以限制计算距离所需的数据范围。 (来自these slides的公式(第12ff页)当您按里程计算时,此方法有效...否则您必须使用正确的公里数值调整“69”。

return

然后你修改你的查询:

1° of latitude ~= 69 miles 
1° of longitude ~= cos(latitude)*69

使用前面提到的经过计算的经度/纬度。

这样可以提高整体速度,而无需更改数据库结构。

答案 1 :(得分:0)

我设法解决了性能问题!

表结构

$result= DB::table('a')->whereIn('cid', [1,2,3,4]);

空间索引

latlng字段具有空间索引,并已填充如下:

+-------------+--------------+------+-----+---------+-------+
| 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    |       |
+-------------+--------------+------+-----+---------+-------+

SQL QUERY

UPDATE uk_postcodes SET latlng = GeomFromText(CONCAT('POINT(',latitude,' ', longitude, ')'));

RESULT

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;