如何构建数据库模式以允许“百万分之一”的情况?

时间:2016-11-01 13:44:13

标签: mysql database-design doctrine-orm

在我的数据库中的所有表中,我有两个目前有Many-to-Many个连接。但是,实际捕获的数据几乎总是具有One-to-Many关联。

考虑到我希望数据库查找(学说查询)尽可能不受阻碍,我应该改为:

  • 在表之间创建两个关联(第二个只是 在这些特殊情况下居住?)
  • 更改关联的数据类型(例如更改为text / tinyblob)以记录2个(或技术上甚至3个)关联记录的迷你数组?

这就是我目前所拥有的(虽然TableB-> JoinTable通常只是一对一):

TableA.id --< a_id.JoinTable.b_id >-- TableB.id

所以,我希望看看我是否可以捕捉'例外'。以下是正确的方法吗?

TableA.id     TableB.id
       +----< TableB.A_id1
       +----- TableB.A_id2
       +----- TableB.A_id3

2 个答案:

答案 0 :(得分:1)

  

更改关联的数据类型(例如更改为text / tinyblob)?

请不要这样做。如果你这样做,那么维护数据库的人就会把你的名字诅咒到千代。不开玩笑。

这里最好的选择是建立一对多的关联。我们假设您的表a有一个整数主键a_id

然后,将a_id作为外键列放在第二个表b中。

您可以按如下方式检索您的信息。对于a中的每一行,这总是会在结果集中为您提供一行。

 SELECT a.this, a.that, GROUP_CONCAT(b.value) value
   FROM a
   LEFT JOIN b ON a.a_id = b.a_id
  GROUP BY a.this, a.that

如果你不介意为百万分之一的情况增加额外的行,那就更容易了。

 SELECT a.this, a.that, b.value
   FROM a
   LEFT JOIN b ON a.a_id = b.a_id

LEFT JOIN操作允许您的a行没有相应的b行。

b.a_id上添加索引。

答案 1 :(得分:1)

您似乎对以下内容感兴趣:

-- a and b are related by the association of interest
Foo(a, b)

-- foo(a, b) but not foo(a2, b) for some a2 <> a
Boring(a, b)
unique(b)
FK (a, b) references Foo

-- foo(a, b) and foo(a2, b) for some a2 <> a
Rare(a, b)
FK (a, b) references foo

如果您希望查询不受阻碍,只需定义Foo即可。您可以查询稀有。

Rare = select * from Foo f join Foo f2
    where f.a <> f2.a and f.b = f2.b

任何其他设计都会因更新复杂性而使数据库保持一致。

你有一些模糊的担心,稀有比Foo小得多。但是你的要求只有百万Foo记录中有多少:很多你会选择其他设计吗?

下一个复杂程度是拥有Foo和Rare。更新必须保持上述等式。

似乎极不可能通过仅使用Boring + Rare并从中重建Foo来减少Foo + Rare的2或3百万个冗余。但是为Boring定义一个唯一的索引(b)可能是有益的,它将保持其中的b只有一个a。当你需要Foo:

Foo = select * from Boring union select * from Rare

但是您的更新必须保持

not exists (select * from Boring b join Rare r where b.b = r.b)