单独的地址表、纬度、经度

Rak*_*h B 5 performance database-design address query-performance

我们正在为功能有限的社交网络应用程序设计数据库。用户(注册用户)、零售店等是我们需要存储的几个实体。我们需要存储每个实体的地址。我们还需要存储注册用户、零售店等的纬度和经度。

最初我们设计了如下所示的表格。我们创建了一个单独的地址表,因为用户、零售店和其他实体的地址格式相同。

User(UserID, UserName, AddressID)
RetailOutlet(RetailOutletID, OutletName, AddressID)
Address(AddressID, CityID, AddressLine1, AddressLine2, Latitude, Longitude)
Run Code Online (Sandbox Code Playgroud)

现在我们意识到我们需要搜索靠近用户当前位置(CurrentLatitude,CurrentLongitude)的零售店,所以我们需要运行一个查询,如

SELECT OutletName 
from RetaileOutlet 
INNER JOIN Address ON RetailOutlet.AddressID = Address.AddressId 
WHERE Address.Latitude BETWEEN CurrentLatitude - 10 and CurrentLatitude + 10 and
      Address.Longitude BETWEEN CurrentLongitude - 10 and CurrentLongitude + 10
Run Code Online (Sandbox Code Playgroud)

现在我们认为上面的查询会运行缓慢,因为用户数量将远远超过零售店数量。从数据库设计/性能的角度来看,应该完成以下哪一项。

  1. 在 Address 表中的 Latitude、Longitude 和 RetailOutlet 表中的 AddressID 上创建索引。所以表结构不会发生变化。

  2. 将纬度、经度从地址表移动到零售店和用户表。还要在 RetailOutlet 表中的纬度、经度上创建索引。所以表结构如下所示。

    User(UserID, UserName, AddressID, Latitude, Longitude)
    RetailOutlet(RetailOutletID, OutletName, AddressID, Latitude, Longitude)
    Address(AddressID, CityID, AddressLine1, AddressLine2)
    
    Run Code Online (Sandbox Code Playgroud)
  3. 如下所示更改表结构,并在 UserAddress 表中的 Lat、Lng 和 User 表中的 UserAddressID 上创建索引。

    User(UserID, UserName, UserAddressID)
    UserAddress(AddressID, CityID, AddressLine1, AddressLine2, Latitude, Longitude)
    RetailOutlet(RetailOutletID, OutletName, AddressID)
    RetailOutletAddress(RetailOutletAddressID, CityID, AddressLine1, AddressLine2, Latitude, Longitude)
    
    Run Code Online (Sandbox Code Playgroud)
  4. 通过从RetailOutlet 表中的Address 表复制Lat、Lng 并在RetailOutlet 表中的Lat、Lng 上创建索引来引入DB 冗余。使用此选项,地址表不会发生变化,我们将能够使用它来存储用户地址而无需更改。我们也可以使用它来存储其他实体的地址。

    User(UserID, UserName, AddressID)
    RetailOutlet(RetailOutletID, OutletName, AddressID, Latitude, Longitude)
    Address(AddressID, CityID, AddressLine1, AddressLine2, Latitude, Longitude)
    
    Run Code Online (Sandbox Code Playgroud)

Dan*_*ons 1

正确的答案是选择 #5:使用PostGIS来自OpenGeo的示例:

\n\n
\n

<->“注意子句中的魔术运算符ORDER BY。这就是魔术发生的地方。这<->是一个 \xe2\x80\x9cdistance\xe2\x80\x9d 运算符,但它仅在出现在子句中时才使用索引ORDER BY。在放置之间ORDER BY使用 and中的运算符来截断结果集,我们可以非常非常快地(在本例中,在 2M 记录表上LIMIT不到10 毫秒)获得距离我们的测试点最近的 10 个点。”

\n
\n\n

(强调已添加)

\n

  • 你怎么知道他正在使用 PostgreSQL?也许他正在使用其他 DBMS? (2认同)