在一般的一对多(父对子)关系中,(a)将parent_id放在子表中和(b)使用只有parent_id,child_id的数据透视表之间是否存在显着的效率差异?
注意:如有必要,请假设Oracle,否则使用常规RDBMS进行回答。
答案 0 :(得分:2)
如果PIVOT
表是many-to-many
表,那么不是,它只会妨碍性能。
您应该在子表中保留parent_id
。
many-to-many
链接表需要额外JOIN
,因此效率较低。
比较以下查询:
SELECT *
FROM child_table c
JOIN child_to_parent cp
ON cp.child = c.id
JOIN parent p
ON p.id = cp.parent
WHERE c.property = 'some_property'
和这一个:
SELECT *
FROM child_table c
JOIN parent p
ON p.id = c.parent
WHERE c.property = 'some_property'
后一个是JOIN
更短且效率更高。
该规则唯一可能的例外是您经常运行这些查询:
SELECT *
FROM child_table c
JOIN parent_table p
ON p.id = c.parent
WHERE c.id IN (id1, id2, ...)
,我。即你事先知道子行的id
。
如果您使用child_table
的自然键,这可能很有用。
在这种情况下,是child_to_parent
链接表会更有效率,因为您可以使用以下查询替换它:
SELECT *
FROM child_to_parent cp
JOIN parent_table p
ON p.id = cp.parent
WHERE cp.child IN (id1, id2, ...)
和child_to_parent
的大小始终小于或等于child_table
,因此效率更高。
但是,在Oracle
中,您可以在child_table (id, parent_id)
上创建复合索引,从而获得相同的结果。
由于Oracle
没有索引NULL
,因此该索引就像您的child_to_parent
表一样,但没有表本身和隐含的维护开销。
在其他系统(索引NULL
)中,索引的效率可能低于专用表,特别是如果您有很多NULL
个父级。