Database design 设计关系数据库-使用分层数据模型还是避免它们?

Database design 设计关系数据库-使用分层数据模型还是避免它们?,database-design,postgresql,hierarchical-data,Database Design,Postgresql,Hierarchical Data,我正在设计一个数据库,我对在关系数据库中使用分层数据模型有些怀疑 如果我想处理类别、子类别和父类别,是否可以不在关系数据库中使用分层数据模型?换言之,是否可以使用关系处理方式处理类别、子类别和父类别 顺便说一下,我正在使用PostgreSQL 对不起,我的英语不好 致以最诚挚的问候,您所说的“分层数据模型”是什么意思?如果您只是指在关系数据库或SQL数据库中建模层次结构,那么这是一种非常常见和合理的做法。关于如何对层次结构进行关系建模,有大量的数据库文献。这样做没有什么“非关系”的 然而,术语层

我正在设计一个数据库,我对在关系数据库中使用分层数据模型有些怀疑

如果我想处理类别、子类别和父类别,是否可以不在关系数据库中使用分层数据模型?换言之,是否可以使用关系处理方式处理类别、子类别和父类别

顺便说一下,我正在使用PostgreSQL

对不起,我的英语不好

致以最诚挚的问候,

您所说的“分层数据模型”是什么意思?如果您只是指在关系数据库或SQL数据库中建模层次结构,那么这是一种非常常见和合理的做法。关于如何对层次结构进行关系建模,有大量的数据库文献。这样做没有什么“非关系”的


然而,术语层次数据模型通常指的是一种DBMS(不是RDBMS或SQL DBMS)。分层/网络/图形DBMS与RDBMS的工作原理不同——它们使用导航或基于指针的模型,而不是关系模型。关系/SQL模型在很大程度上(但不是完全)取代了这种类型的DBMS。除非您碰巧使用的是分层类型的DBMS,否则您不必担心它。

您有几个选项来存储层次结构:

  • 邻接表
  • 邻接表的递归查询
  • 路径枚举
  • 嵌套集
  • 闭合表
如果您使用的是PostgreSQL 8.4或更高版本,则可以使用使事情变得非常简单。这是迄今为止最简单的解决方案,易于查询,易于插入新记录,易于更新当前记录,易于删除记录,并且您具有引用完整性。所有其他解决方案都有难以解决的部分

邻接列表:

CREATE TABLE categories ( 
  id SERIAL PRIMARY KEY, 
  parent_id BIGINT, 
  category TEXT NOT NULL, 
  FOREIGN KEY (parent_id) REFERENCES categories(id) 
);

INSERT INTO categories(parent_id, category) VALUES(NULL, 'vehicles');
INSERT INTO categories(parent_id, category) VALUES(1, 'cars');
INSERT INTO categories(parent_id, category) VALUES(1, 'motorcycles');
INSERT INTO categories(parent_id, category) VALUES(2, 'SUV');
INSERT INTO categories(parent_id, category) VALUES(2, 'sport');
INSERT INTO categories(parent_id, category) VALUES(3, 'cruising'); 
INSERT INTO categories(parent_id, category) VALUES(3, 'sport'); 


WITH RECURSIVE tree (id, parent_id, category, category_tree, depth) 
AS ( 
    SELECT 
        id,
        parent_id,
        category,
        category AS category_tree,
        0 AS depth 
    FROM categories 
    WHERE parent_id IS NULL 
UNION ALL 
    SELECT 
        c.id,
        c.parent_id,
        c.category,
        tree.category_tree || '/' || c.category AS category_tree,
        depth+1 AS depth 
    FROM tree 
        JOIN categories c ON (tree.id = c.parent_id) 
) 
SELECT * FROM tree ORDER BY category_tree;
结果:

“1”、“车辆”、“车辆”、“0”

‘2’、‘1’、‘汽车’、‘汽车/汽车’、‘1’

‘4’、‘2’、‘SUV’、‘车辆/汽车/SUV’、‘2’

‘5’、‘2’、‘sport’、‘vehicle/cars/sport’、‘2’

‘3’、‘1’、‘摩托车’、‘车辆/摩托车’、‘1’

‘6’、‘3’、‘巡航’、‘车辆/摩托车/巡航’、‘2’

‘7’、‘3’、‘运动’、‘车辆/摩托车/运动’、‘2’


如果您使用的是Postgres,则可以将层次结构作为一个数组存储在数组中


您还可以从使用这种方法的GIN索引中获益,在我的实验中,这种方法比递归查询具有更好的性能。

+1用于指出递归查询(现在有很多DBMS支持)是如何检索层次结构和行深度的非常好的示例。然后可以使用深度进行拓扑排序(按深度排序)。有关选项列表、进一步阅读和注释操作(如祖先检索和节点插入时间)的成本,请参见此问题:如何为此类列创建GIN索引?与创建任何旧索引的方法相同:
使用GIN在表上创建索引名(列);
()