Database design 设计关系数据库-使用分层数据模型还是避免它们?
我正在设计一个数据库,我对在关系数据库中使用分层数据模型有些怀疑 如果我想处理类别、子类别和父类别,是否可以不在关系数据库中使用分层数据模型?换言之,是否可以使用关系处理方式处理类别、子类别和父类别 顺便说一下,我正在使用PostgreSQL 对不起,我的英语不好 致以最诚挚的问候,您所说的“分层数据模型”是什么意思?如果您只是指在关系数据库或SQL数据库中建模层次结构,那么这是一种非常常见和合理的做法。关于如何对层次结构进行关系建模,有大量的数据库文献。这样做没有什么“非关系”的Database design 设计关系数据库-使用分层数据模型还是避免它们?,database-design,postgresql,hierarchical-data,Database Design,Postgresql,Hierarchical Data,我正在设计一个数据库,我对在关系数据库中使用分层数据模型有些怀疑 如果我想处理类别、子类别和父类别,是否可以不在关系数据库中使用分层数据模型?换言之,是否可以使用关系处理方式处理类别、子类别和父类别 顺便说一下,我正在使用PostgreSQL 对不起,我的英语不好 致以最诚挚的问候,您所说的“分层数据模型”是什么意思?如果您只是指在关系数据库或SQL数据库中建模层次结构,那么这是一种非常常见和合理的做法。关于如何对层次结构进行关系建模,有大量的数据库文献。这样做没有什么“非关系”的 然而,术语层
然而,术语层次数据模型通常指的是一种DBMS(不是RDBMS或SQL DBMS)。分层/网络/图形DBMS与RDBMS的工作原理不同——它们使用导航或基于指针的模型,而不是关系模型。关系/SQL模型在很大程度上(但不是完全)取代了这种类型的DBMS。除非您碰巧使用的是分层类型的DBMS,否则您不必担心它。您有几个选项来存储层次结构:
- 邻接表
- 邻接表的递归查询
- 路径枚举
- 嵌套集
- 闭合表
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在表上创建索引名(列);
()