将分层对象存储在栅格中



假设我有一个画布,其中有我可以添加的各种对象,例如a/an:

  • 绘图
  • 图像
  • 图表
  • 备注

对于每个对象,我需要存储尺寸和层顺序,例如:

  • 对象ID
  • 分层索引
  • 尺寸((x1,y1),(x2,y2))

每个对象都有非常不同的属性,因此存储在不同的表(或类或其他什么)中。有可能将其存储到关系数据库中吗?如果有,如何做到这一点?在JSON中,它应该是这样的:

// LayerIndex is the ArrayIndex
// No need to store ObjectID, since the object is stored within the array itself
Layers = [
{Type: Drawing, Props: <DrawingPropertyObj>, Dimensions: [(1,2), (3,4)]},
{Type: Chart,   Props: <ChartPropertyObj>,   Dimensions: [(3,4), (10,4)]},
{Type: Table,   Props: <TablePropertyObj>,   Dimensions: [(10,20), (30,44)]},
...
]

我想到的一个选项是为每个表存储一个FK,但在这种情况下,我可能会将其连接到每个对象类型的N个不同表中,所以如果有100个对象类型。。。

A"严格的";关系数据库不适合这个任务,因为您只能选择:

  1. 每个对象类型都有不同的表,每个属性都有一列应用于特定对象类型
  2. 所有对象类型的单个表,每个属性都有列,其中大多数不用于任何给定的对象类型
  3. 一个子表,每个属性一行

在转到一个好的通用解决方案之前。,让我们讨论一下:

1.每种对象类型都有不同的表

这是一个不启动。问题是:

  • 高昂的维护成本:每次向应用程序添加新的对象类型时,都必须创建一个新表
  • 痛苦的查询:您必须连接到每个表,要么水平连接到一个非常长的行中,要么垂直连接到一系列未连接的连接中,从而生成稀疏数组(请参见选项2)

2.用于所有对象类型的单个表

尽管您处理的是稀疏数组,但如果大多数对象类型使用大多数属性(即不是稀疏),这是一个不错的选择。然而,如果域中不同属性的数量很高,并且/或者大多数属性不是所有类型都使用的,则在引入新类型时必须添加列,尽管这比添加表要好,但仍然需要对新类型进行架构更改=高维护

3.儿童餐桌

这是一种经典的方法,但使用起来更糟,因为您要么必须运行一个单独的查询来收集每个对象的所有属性(缓慢、高维护),要么为每个对象类型编写单独的查询,为每个属性连接一次子表,将多行扁平化为每个对象的一行,有效地产生了选项1,但是写查询的维护成本甚至更高

这些都不是很好的选择。你想要的是:

  • 每个对象一行
  • 简单查询
  • 简单架构
  • 低维护

文档数据库,如Elasticsearch,可以开箱即用地为您提供所有这些功能,但您可以通过放松";严格性";并将整个对象保存为一列中的json:

create table object (
id int, -- typically auto incrementing
-- FK to parent - see below
json text -- store object as json
);

顺便说一句,postgres是一个不错的选择,因为它通过json数据类型对json有原生支持。

在我的职业生涯中,我已经用过好几次了,总是很成功。我为对象类类型添加了一列(在java上下文中):

create table object (
id int,
-- FK to parent - see below
class_name text,
json text
);

并使用json库将使用指定类的json反序列化为该类的对象。无论你使用什么语言,都有办法实现这个想法。

至于层次结构,关系数据库可以很好地做到这一点。来自画布:

create table canvas (
id int,
-- various attributes
);

如果对象未被重用:

create table object (
id int,
canvas_id int not null references canvas,
class_name text,
json text,
layer int not null
);   

如果对象被重复使用:

如果对象未被重用:

create table object (
id int,
class_name text,
json text
);
create table canvas_object (
canvas_id int not null references canvas,
object_id int not null references object,
layer int not null
);

您有许多选项,如下所示。

你选择哪一个没有太大区别,但我会避免你所说的多桌设计。一个具有100个属性的对象类型将被分散在101个表中而没有增益。针对正在读取的每种对象类型进行101次磁盘页面访问。这是不必要的(如果这些页面被缓存,那么这个问题会比其他情况下小,但仍然是浪费)。

如果你不想过滤"所有颜色为红色的对象"之类的东西,即使是双表也不是真正必要的,但我想性能并不是那么迫切需要达到这一点,其他事情更重要,或者其他瓶颈对性能的影响更大,所以从不超过双表中选择一个最适合你的。

单表-每个对象类型的灵活架构

道具<1>y1<1><11><22>>44
objectlayerindex 类型x0y0x1
0 绘图 {颜色:#00FF00,背景色:#00FFFF}234
1 图表 {标题:2021_sales,值:[[0,0],[3,4]]}33

最新更新