3

我需要在我的网页上显示一个城市附近所有位置的距离矩阵。

我想从网络服务中获取所有这些数据并提前保存在我的数据库中。我试图找出最好的关系数据库设计来保存这样的数据。

我想避免冗余数据以及提供最佳性能的设计。

我知道关系 DB 不是最好的选择,但在这一点上我无能为力。

问题:那么存储此类信息的最佳数据库模式设计是什么。我需要查询仅提供一个城市的数据库,并且必须显示一个包含 5 个或 10 个最近城市的矩阵。

旅行时间并不那么重要,我主要关心的是距离。

这种矩阵减去持续时间

4

2 回答 2

3

为了性能,假设您使用的是 InnoDB,我可能会对数据进行一些非规范化,如下所示:

CREATE TABLE CITY (
    CITY_ID INT PRIMARY KEY
);

CREATE TABLE CITY_DISTANCE (
    CITY1_ID INT,
    CITY2_ID INT,
    DISTANCE NUMERIC NOT NULL,
    PRIMARY KEY (CITY1_ID, DISTANCE, CITY2_ID),
    FOREIGN KEY (CITY1_ID) REFERENCES CITY (CITY_ID),
    FOREIGN KEY (CITY2_ID) REFERENCES CITY (CITY_ID)
);

每对城市在 CITY_DISTANCE 中有 2 行包含相同的 DISTANCE(每个方向一个)。这显然会使其变得非常大并可能导致数据不一致(数据库不会保护自己免受同一城市之间不匹配的 DISTANCE 值的影响),并且 DISTANCE 在逻辑上不属于 PK,但请耐心等待...

InnoDB 表是 clustered,这意味着通过以这种特殊方式声明 PK,我们将整个表放在特别适合如下查询的 B-Tree 中:

SELECT CITY2_ID, DISTANCE
FROM CITY_DISTANCE
WHERE CITY1_ID = 1
ORDER BY DISTANCE
LIMIT 5

该查询返回与 标识的城市最近的 5 个城市1,可以通过对上述 B-Tree 的简单范围扫描来满足:

id  select_type table           type    possible_keys   key     key_len ref     rows    Extra
1   SIMPLE      CITY_DISTANCE   ref     PRIMARY         PRIMARY 4       const   6       "Using where; Using index"

顺便说一句,由于第二个 FK,InnoDB 将自动再创建一个索引(在 CITY2_ID 上),它还将包括 CITY1_ID 和 DISTANCE,因为聚集表中的二级索引必须覆盖 PK。您也许可以利用它来避免重复的 DISTANCE(在 {CITY2_ID, DISTANCE, CITY1_ID} 上显式创建索引并让 FK 重用它,并检查 (CITY1_ID < CITY2_ID)),但 MySQL 查询优化器可能不够聪明,无法处理这种结构所需的查询。

于 2012-09-11T12:05:06.223 回答
0

最简单的方法是存储一对城市以及距离和您希望能够显示的任何其他数据。我会将城市本身存储在一个单独的表中,并且只将两个键和距离信息存储在距离表中。

我确定您最多只想显示最接近的 5 或 10 个,您可以从仅添加这些记录开始。这意味着对于 N 个城市,您只会在数据库中获得 N*10 条记录,这应该是相当可扩展的。

即使有大量记录,如果添加适当的索引,性能也应该不错。

于 2012-09-11T05:43:57.910 回答