在数据库中组织主键的更好方法是什么?

时间:2012-11-03 10:43:24

标签: sql oracle database-design primary-key

我的数据库有两个表,一个是城市的距离矩阵,另一个是城市。我的第一个结构是这样的:

    • UUID
    • 名称
    • 纬度
    • 经度

  • 距离
    • FromCityID
    • ToCityID
    • DistanceLength

UUID是CITY表的主键,FromCityIDToCityID引用CITY作为外键,两者都是DISTANCE表的复合主键,因为两者之间的距离城市应该是独一无二的。

然后我意识到我不想使用UUID并自动增加主键,因为我从XML上传数据,这些数据包含城市和距离。并且距离可能不仅包括当前XML中提到的那些城市,而且还包括来自数据库的任何先前存储的城市。

我需要一个在数据库和XML中相同的ID系统。纬度/经度似乎是最佳选择,因此我将表格更改为:

    • 名称
    • 纬度
    • 经度

  • 距离
    • FromCityIDLatitude
    • FromCityIDLongitude
    • ToCityIDLatitude
    • ToCityIDLongitude
    • DistanceLength

LatitudeLongitude是CITY表的复合主键; FromCityIDLatitude / FromCityIDLongitudeToCityIDLatitude / ToCityIDLongitude引用CITY作为外键,所有四列都是DISTANCE表的复合主键。

但是使用4列作为主键是一个糟糕的设计。在这种情况下最好的是什么?

3 个答案:

答案 0 :(得分:3)

我不同意这句话:

  

但是使用4列作为主键是一个糟糕的设计。

糟糕的设计是指不能满足您需要的设计或允许数据库不一致的设计。在您的情况下,只要我们做出一个假设,我就不会发现四列主键有问题。也就是说,您对此表的主要访问路径将使用主键中的每个列。如果是这样的话,那很好;我会将整个表放入一个唯一的索引中,并在密钥的四列上添加一个单独的唯一约束。

四列索引的问题是当您尝试通过第四个叶子访问该表时。您可能根本不会使用索引。如果有必要定期在第四片叶子上进行索引查找,则必须添加另一个索引等。最终可能会出现一个可笑的过度索引表。

绕过它的方式是错开装载。不要将XML数据直接加载到主数据库表中。将它们加载到辅助表中并运行一个进程以查看该城市是否已存在。如果是,则不添加它。如果没有,则生成新的代理键并执行CROSS JOIN将所有新记录添加到DISTANCE。

答案 1 :(得分:1)

不要忘记桌子的“物理”设计。对于距离矩阵,请考虑使用索引组织表(IOT),并压缩列。

请参阅AskTom上关于类似问题(关于距离表)的讨论:

http://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:239614547000#52902724002052

答案 2 :(得分:0)

要回答标题中提到的问题,

  

在数据库中组织主键的更好方法是什么?

盲键(整数或通用唯一标识符)几乎总是更好地作为键。他们永远不需要改变。数据元素可能会也可能不会发生变化。

在您的特定情况下,城市的纬度和经度不太可能发生变化。但是,如果您收到城市的纬度/经度校正,则现在必须在两个表格中进行校正。