SQL - 多对多表主键

And*_*ite 118 sql many-to-many primary-key

在阅读此问题中的评论后,会出现此问题:

数据库设计

创建多对多表时,应该在两个外键列上创建复合主键,还是创建自动增量代理"ID"主键,并将索引放在两个FK列上(也许一个独特的约束)?在每种情况下插入新记录/重新索引对性能有何影响?

基本上,这个:

PartDevice
----------
PartID (PK/FK)
DeviceID (PK/FK)
Run Code Online (Sandbox Code Playgroud)

与此:

PartDevice
----------
ID (PK/auto-increment)
PartID (FK)
DeviceID (FK)
Run Code Online (Sandbox Code Playgroud)

评论者说:

使两个ID成为PK意味着表按照该顺序在磁盘上进行物理排序.因此,如果我们插入(Part1/Device1),(Part1/Device2),(Part2/Device3),然后(Part1/Device3),数据库必须将表拆开并在条目2和3之间插入最后一个.许多记录,这变得非常有问题,因为它涉及每次添加一个数据,数千或数百万条记录.相比之下,自动增量PK允许将新记录添加到最后.

我问的原因是因为我一直倾向于使用没有代理自动增量列的复合主键,但我不确定代理键是否实际上更具性能.

pax*_*blo 80

通过简单的两列多对多映射,我发现拥有代理键​​没有真正的优势.(col1,col2)确保主键处于唯一状态(假设您在引用表中的值col1col2值是唯一的),并且单独的索引(col2,col1)将捕获相反顺序执行速度更快的情况.代理是浪费空间.

您不需要在各个列上使用索引,因为该表只应用于将两个引用的表连接在一起.

在我看来,你在问题中提到的评论不值得它使用的电子.听起来像作者认为表存储在一个数组中,而不是一个极高性能的平衡多路树结构.

首先,它永远不需要存储或获取排序的,只需索引.并且索引不会按顺序存储,它将以有效的方式存储,以便能够快速检索.

此外,绝大多数数据库表的读取频率远远超过书面表.这使得你在选择方面所做的任何事情都比插入方面的任何东西都更具相关性.

  • @buffer,是的,但是,这些订单中的每一个几乎肯定会被多次查询(例如)打包,计费,状态更新,业务分析等等.创建的绝对数量不如创建和读取之间的_ratio_重要. (8认同)
  • @buffer,我会坚持这个评论(从技术上讲,只有当我说"所有表格","绝大多数"是基于经验时,这是一种概括).让我们考虑一下你的例子,订单创建一次(它可能偶尔更新,但不太可能改变键/索引信息,更多的是点击订单状态.但是,这些更新和你需要做的选择打印出发票或生成管理报告将超过原始插入. (4认同)
  • 我的观点是,如果每小时执行数千次,“插入”将很重要。你不能仅仅因为 `insert` 和 `select` 的比率 < 1 就忽略它。在这种情况下,客户关心下订单需要多长时间。 (2认同)

gbn*_*gbn 18

链接表不需要代理键.

您需要一个PK(col1,col2)和另一个(col2,col1)上的唯一索引

除非您使用的ORM无法应对并决定您的数据库设计...

编辑:我在这里回答了同样的问题:SQL:你需要一个自动增量主键用于许多表吗?

  • 您可以在col2上使用dups索引而不是(col2,col1)上的唯一索引.双列索引的优点是它允许单独使用col2或在col1和col2上进行仅索引扫描(尽管另一个索引on(col1,col2)也处理'both').缺点是额外列需要额外的存储空间.这通常不重要,所以建议远非糟糕.然而,如果col1和col2很大或者大小不同,你可以通过选择在较短的列上选择第二个索引来节省一些空间而不会损害性能. (3认同)
  • 在 (col1, col2) 已经是 PK 后为其添加唯一索引是完全多余的 (3认同)
  • @mmcrae:您的评论是“在(col1,col2)上放置唯一索引。”。索引中的列顺序很重要。`(col2,col1)`不是`(col1,col2)`。((col1,col2))的PK可能不适用于所有查询并生成扫描,因此将其取反可以提高性能,因为它允许查找col2更好的地方。例如,当带有col2的表具有删除时,进行FK验证。子表smuts被检查 (2认同)

Jro*_*nny 12

如果引用该表,则可能需要增量主键.多对多表中可能存在需要使用增量主键从另一个表中提取的详细信息.

例如

PartDevice
----------
ID (PK/auto-increment)
PartID (FK)
DeviceID (FK)
Other Details
Run Code Online (Sandbox Code Playgroud)

使用PartDevice.ID作为FK很容易拉出"其他细节".因此,需要使用增量主键.


Ber*_*ann 6

我能回答你问题的最简单,最直接的方法是,如果你链接的两个表没有连续的主键,会对性能产生影响.如您所述/引用的那样,链接表的索引将变为碎片,或者如果链接表没有自己的顺序主键,DBMS将更加努力地插入记录.这就是大多数人在链接表上放置顺序递增主键的原因.