Mysql 关系数据库设计:如何设计具有长路径的关系?

Mysql 关系数据库设计:如何设计具有长路径的关系?,mysql,database-design,orm,relational-database,entity-relationship,Mysql,Database Design,Orm,Relational Database,Entity Relationship,我目前正在设计一个MySQL数据库,我遇到了以下问题,我不确定如何正确地解决/设计 我有实体:(简化) 现在: 所以现在我在PHP中使用这个数据库模型的ORM,我发现自己有一个传真对象的实例,需要加载相应的提供者 现在,这要么会花费我一个大的加入,要么会花费我几个查询 我需要走的道路是: Fax -> Letter -> Address -> Provider 现在我在想,我是否应该在传真和提供商之间建立直接关系,这将解决这个问题。但这难道不是多余的,而且要付出双倍的努力吗?

我目前正在设计一个MySQL数据库,我遇到了以下问题,我不确定如何正确地解决/设计

我有实体:(简化)

现在:

所以现在我在PHP中使用这个数据库模型的ORM,我发现自己有一个传真对象的实例,需要加载相应的提供者

现在,这要么会花费我一个大的加入,要么会花费我几个查询

我需要走的道路是:

Fax -> Letter -> Address -> Provider
现在我在想,我是否应该在传真和提供商之间建立直接关系,这将解决这个问题。但这难道不是多余的,而且要付出双倍的努力吗?如果传真和提供商之间的关系发生变化怎么办?然后我会调整两种关系路径


这样做的首选方式是什么?我的例子有点简化。实际上,我必须走的路要长一点

您可以做的是使提供者的后续表彼此关联为-其中每个表的标识主键的一部分依赖于另一个表(通过1:N标识关系)。您可以这样建模:

providers
-----------------
provider_id   [PK]
...


addresses
-----------------
provider_id   [PK] (FK Referencing providers.provider_id)
address_id    [PK]
...


letters
-----------------
provider_id   [PK] (FK Referencing addresses.provider_id)
address_id    [PK] (FK Referencing addresses.address_id)
letter_id     [PK]
...


faxes
-----------------
provider_id   [PK] (FK Referencing letters.provider_id)
address_id    [PK] (FK Referencing letters.address_id)
letter_id     [PK] (FK Referencing letters.letter_id)
fax_id        [PK]
...
这样,给定一个特定的传真记录,您只需查找有关关联提供商的更多信息,您只需加入一个表,如下所示:

SELECT 
    subj,
    content
FROM
    faxes
INNER JOIN
    providers USING (provider_id)
WHERE
    fax_id = <faxid here>
选择
Subc,
所容纳之物
从…起
传真
内连接
提供程序使用(提供程序\u id)
哪里
传真号码=

您可以做的是使提供者的后续表彼此关联为-其中每个表的标识主键的一部分依赖于另一个表(通过1:N标识关系)。您可以这样建模:

providers
-----------------
provider_id   [PK]
...


addresses
-----------------
provider_id   [PK] (FK Referencing providers.provider_id)
address_id    [PK]
...


letters
-----------------
provider_id   [PK] (FK Referencing addresses.provider_id)
address_id    [PK] (FK Referencing addresses.address_id)
letter_id     [PK]
...


faxes
-----------------
provider_id   [PK] (FK Referencing letters.provider_id)
address_id    [PK] (FK Referencing letters.address_id)
letter_id     [PK] (FK Referencing letters.letter_id)
fax_id        [PK]
...
这样,给定一个特定的传真记录,您只需查找有关关联提供商的更多信息,您只需加入一个表,如下所示:

SELECT 
    subj,
    content
FROM
    faxes
INNER JOIN
    providers USING (provider_id)
WHERE
    fax_id = <faxid here>
选择
Subc,
所容纳之物
从…起
传真
内连接
提供程序使用(提供程序\u id)
哪里
传真号码=

嗯,识别关系和“更自然”的键可以降低加入的需要

例如:

由于存在
传真.ProviderId
,因此您可以直接加入
传真
提供商

而且,如果您选择相反的方向(例如“获取给定提供商的所有传真”),您可以期望获得良好的性能


缺点是“更胖”的键和对ORM的相对不友好。所以,我想这是一个折衷的问题,你是决定哪种选择更好的人。

好吧,确定关系和“更自然”的键可以降低加入的需要

例如:

由于存在
传真.ProviderId
,因此您可以直接加入
传真
提供商

而且,如果您选择相反的方向(例如“获取给定提供商的所有传真”),您可以期望获得良好的性能


缺点是“更胖”的键和对ORM的相对不友好。所以,我想这是一个折衷的问题,由你来决定哪个选项更好。

谢谢。OffTopic:请问您是如何绘制图表的?@Norwald2 Microsoft Visio,使用“软件和数据库/数据库模型图表”绘图类型。然后导出到PNG并上传到SO。比如说,当一个地址连接到另一个提供商时,我必须手动更新信件和传真中ProviderId的所有外键。@Norwald2它们需要更新,但是你不必手动操作-这可以通过更新级联自动完成。过去我想知道更新级联在哪里有用:)谢谢你的帮助。我明天会试试。谢谢。OffTopic:请问您是如何绘制图表的?@Norwald2 Microsoft Visio,使用“软件和数据库/数据库模型图表”绘图类型。然后导出到PNG并上传到SO。比如说,当一个地址连接到另一个提供商时,我必须手动更新信件和传真中ProviderId的所有外键。@Norwald2它们需要更新,但是你不必手动操作-这可以通过更新级联自动完成。过去我想知道更新级联在哪里有用:)谢谢你的帮助。我明天会试试看。