在网格中存储分层对象
Storing layered objects in a grid
假设我有一个 canvas,我可以在其中添加各种对象,例如 a/an:
- 绘图
- 图片
- 图表
- 备注
- Table
对于每个对象,我需要存储尺寸和层顺序,例如这样的东西:
- 对象ID
- 图层索引
- 尺寸((x1,y1),(x2,y2))
每个对象都具有截然不同的属性,因此存储在不同的 table 中(或 类 或其他)。是否可以将其存储到关系数据库中,如果可以,如何实现?在 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)]},
...
]
我想到的一个选择是为每个 table 存储一个 FK,但在那种情况下,我可能会将其加入每个对象类型的 N 个不同的 table,所以如果有是 100 种对象类型,...
您有很多选项,如下所示。
你选哪个没有太大区别,但我会避免你说的multi-table设计。具有 100 个属性的 object 类型将分散在 101 table 秒中而没有任何收益。正在读取的每个 object 类型有 101 次磁盘页面访问。这是不必要的(如果这些页面被缓存,那么这个问题会比其他情况少,但仍然是浪费)。
如果你不想过滤像'all objects with color=red'这样的东西,即使是双table也不是真正必要的,但我想达到这一点性能并不是那么迫切,其他事情更重要,或其他瓶颈对性能的影响更大,因此请选择最适合您的 no-more-than-dual-table。
单个 table - 每个 object 类型的灵活模式
objlayerindex
type
props
x0
y0
x1
y1
0
drawing
{color:#00FF00,background-color:#00FFFF}
1
2
3
4
1
chart
{title:2021_sales,values:[[0,0],[3,4]]}
11
22
33
44
- props中的key是为了灵活使用,不同的object同类型的可能有不同的key,比如没有字幕的图表可以省略这个key。
单一 table - 每个 object 类型的固定架构
objlayerindex
type
props
x0
y0
x1
y1
0
drawing
#00FF00,#00FFFF
1
2
3
4
1
chart
2021_sales,"[[0,0],[3,4]]"
11
22
33
44
- 这个模式是固定的——绘图总是有颜色+背景颜色;图表总是有标题+值;等 - 较少 space 使用但更改模式涉及对现有数据的一些工作。
双table
主要
objlayerindex
type
x0
y0
x1
y1
0
drawing
1
2
3
4
1
chart
11
22
33
44
属性
objlayerindex
propertyname
propertyvalue
0
color
#00FF00
0
background-color
#00FFFF
1
title
2021_sales
1
values
[[0,0],[3,4]]
- 这里我们假设 属性 顺序不重要。如果是,则需要一个额外的列
propertyindex
。对于那些喜欢归一化的人来说,也可以从这个 table 中取出 propertyname
到一个 propertykey-propertydescription
并通过它的 propertykey
. 引用它
多个table
主要
objlayerindex
type
x0
y0
x1
y1
0
drawing
1
2
3
4
1
chart
11
22
33
44
颜色
objlayerindex
colorcode
0
#00FF00
Background-Color
objlayerindex
colorcode
0
#00FFFF
标题
objlayerindex
title
1
2021_sales
值
objilayerindex
chart
1
[[0,0],[3,4]]
- 具体这种数据可以多归一化一级:
值
objlayerindex
datapoint
x
y
1
0
0
0
1
1
3
4
您也可以使用 non-relational 格式。
文档(Json)存储
[
{type:drawing,props:{color:#00FF0,background-color:#00FF0},position:[1,2,3,4]},
{type:chart,props:{title:2021_sales,values:[[0,0],[3,4]]},position:[11,22,33,44]}
]
- 我们在这里引用是因为它是一种流行且简单的格式,但是可以使用不同的编码来代替 JSON(CSV、protocolbuffers、avro 等)
“严格”的关系数据库不适合这项任务,因为您可以选择:
- 每个 object 类型的不同 tables,每个属性都有一个列,适用于该特定 object 类型
- 所有 object 类型的单个 table,每个属性都有列,其中大部分不用于任何给定的 object 类型
- A child table,每个属性一行
在继续讨论一个好的通用解决方案之前,让我们讨论一下:
1。每个 object 类型 table 不同
这是一个non-starter。问题是:
- 高维护成本:每次向应用程序添加新的 object 类型时都必须创建一个新的 table
- 痛苦的查询:您必须连接到每个 table,或者水平连接 - 每个 table 连接成一个非常长的行,或者垂直连接到一系列联合连接,导致 sparse array(见选项 2)
2。所有 object 类型
的单个 table
虽然你处理的是sparse array,但如果大多数object类型使用大部分属性(即不是那个稀疏),这是一个不错的选择。但是,如果您的域中不同属性的数量很多,and/or 大多数属性并未被所有类型使用,您必须在引入新类型时添加列,尽管这比添加 table 更好s,仍然需要为新类型更改架构 = 高维护
3。 Achildtable
这是 classic 方法,但使用起来更糟糕,因为您必须 运行 一个单独的查询来收集每个 object 的所有属性(慢, 高维护), or 为每个 object 类型编写单独的查询, 为每个属性加入 child table 一次以压平许多将每个 object 的行分成一行,有效地导致选项 1,但编写查询的维护成本更高
None 这些都是很好的选择。你要的是:
- 每行一行 object
- 简单查询
- 简单架构
- 低维护
A document database, such as Elasticsearch 为您提供了开箱即用的所有这些,但是您可以通过放宽“严格性”并将整个 object 保存为 [=92 来使用关系数据库实现相同的效果=] 在单列中:
create table object (
id int, -- typically auto incrementing
-- FK to parent - see below
json text -- store object as json
);
顺便说一句,postgres 将是一个不错的选择,因为它通过 json
数据类型具有 native support for json。
我在我的职业生涯中使用过几次,每次都成功。我为 object class 类型添加了一列(在 java 上下文中):
create table object (
id int,
-- FK to parent - see below
class_name text,
json text
);
并使用 json 库将使用指定 class 的 json 反序列化为 class 的 object。无论您使用何种语言,都可以通过某种方式实现这一想法。
至于层次结构,关系数据库做得很好。来自 canvas:
create table canvas (
id int,
-- various attributes
);
如果 object 没有重复使用:
create table object (
id int,
canvas_id int not null references canvas,
class_name text,
json text,
layer int not null
);
如果 object 被重复使用:
如果 object 没有重复使用:
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
);
假设我有一个 canvas,我可以在其中添加各种对象,例如 a/an:
- 绘图
- 图片
- 图表
- 备注
- Table
对于每个对象,我需要存储尺寸和层顺序,例如这样的东西:
- 对象ID
- 图层索引
- 尺寸((x1,y1),(x2,y2))
每个对象都具有截然不同的属性,因此存储在不同的 table 中(或 类 或其他)。是否可以将其存储到关系数据库中,如果可以,如何实现?在 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)]},
...
]
我想到的一个选择是为每个 table 存储一个 FK,但在那种情况下,我可能会将其加入每个对象类型的 N 个不同的 table,所以如果有是 100 种对象类型,...
您有很多选项,如下所示。
你选哪个没有太大区别,但我会避免你说的multi-table设计。具有 100 个属性的 object 类型将分散在 101 table 秒中而没有任何收益。正在读取的每个 object 类型有 101 次磁盘页面访问。这是不必要的(如果这些页面被缓存,那么这个问题会比其他情况少,但仍然是浪费)。
如果你不想过滤像'all objects with color=red'这样的东西,即使是双table也不是真正必要的,但我想达到这一点性能并不是那么迫切,其他事情更重要,或其他瓶颈对性能的影响更大,因此请选择最适合您的 no-more-than-dual-table。
单个 table - 每个 object 类型的灵活模式
objlayerindex | type | props | x0 | y0 | x1 | y1 |
---|---|---|---|---|---|---|
0 | drawing | {color:#00FF00,background-color:#00FFFF} | 1 | 2 | 3 | 4 |
1 | chart | {title:2021_sales,values:[[0,0],[3,4]]} | 11 | 22 | 33 | 44 |
- props中的key是为了灵活使用,不同的object同类型的可能有不同的key,比如没有字幕的图表可以省略这个key。
单一 table - 每个 object 类型的固定架构
objlayerindex | type | props | x0 | y0 | x1 | y1 |
---|---|---|---|---|---|---|
0 | drawing | #00FF00,#00FFFF | 1 | 2 | 3 | 4 |
1 | chart | 2021_sales,"[[0,0],[3,4]]" | 11 | 22 | 33 | 44 |
- 这个模式是固定的——绘图总是有颜色+背景颜色;图表总是有标题+值;等 - 较少 space 使用但更改模式涉及对现有数据的一些工作。
双table
主要
objlayerindex | type | x0 | y0 | x1 | y1 |
---|---|---|---|---|---|
0 | drawing | 1 | 2 | 3 | 4 |
1 | chart | 11 | 22 | 33 | 44 |
属性
objlayerindex | propertyname | propertyvalue |
---|---|---|
0 | color | #00FF00 |
0 | background-color | #00FFFF |
1 | title | 2021_sales |
1 | values | [[0,0],[3,4]] |
- 这里我们假设 属性 顺序不重要。如果是,则需要一个额外的列
propertyindex
。对于那些喜欢归一化的人来说,也可以从这个 table 中取出propertyname
到一个propertykey-propertydescription
并通过它的propertykey
. 引用它
多个table
主要
objlayerindex | type | x0 | y0 | x1 | y1 |
---|---|---|---|---|---|
0 | drawing | 1 | 2 | 3 | 4 |
1 | chart | 11 | 22 | 33 | 44 |
颜色
objlayerindex | colorcode |
---|---|
0 | #00FF00 |
Background-Color
objlayerindex | colorcode |
---|---|
0 | #00FFFF |
标题
objlayerindex | title |
---|---|
1 | 2021_sales |
值
objilayerindex | chart |
---|---|
1 | [[0,0],[3,4]] |
- 具体这种数据可以多归一化一级:
值
objlayerindex | datapoint | x | y |
---|---|---|---|
1 | 0 | 0 | 0 |
1 | 1 | 3 | 4 |
您也可以使用 non-relational 格式。
文档(Json)存储
[
{type:drawing,props:{color:#00FF0,background-color:#00FF0},position:[1,2,3,4]},
{type:chart,props:{title:2021_sales,values:[[0,0],[3,4]]},position:[11,22,33,44]}
]
- 我们在这里引用是因为它是一种流行且简单的格式,但是可以使用不同的编码来代替 JSON(CSV、protocolbuffers、avro 等)
“严格”的关系数据库不适合这项任务,因为您可以选择:
- 每个 object 类型的不同 tables,每个属性都有一个列,适用于该特定 object 类型
- 所有 object 类型的单个 table,每个属性都有列,其中大部分不用于任何给定的 object 类型
- A child table,每个属性一行
在继续讨论一个好的通用解决方案之前,让我们讨论一下:
1。每个 object 类型 table 不同
这是一个non-starter。问题是:
- 高维护成本:每次向应用程序添加新的 object 类型时都必须创建一个新的 table
- 痛苦的查询:您必须连接到每个 table,或者水平连接 - 每个 table 连接成一个非常长的行,或者垂直连接到一系列联合连接,导致 sparse array(见选项 2)
2。所有 object 类型
的单个 table虽然你处理的是sparse array,但如果大多数object类型使用大部分属性(即不是那个稀疏),这是一个不错的选择。但是,如果您的域中不同属性的数量很多,and/or 大多数属性并未被所有类型使用,您必须在引入新类型时添加列,尽管这比添加 table 更好s,仍然需要为新类型更改架构 = 高维护
3。 Achildtable
这是 classic 方法,但使用起来更糟糕,因为您必须 运行 一个单独的查询来收集每个 object 的所有属性(慢, 高维护), or 为每个 object 类型编写单独的查询, 为每个属性加入 child table 一次以压平许多将每个 object 的行分成一行,有效地导致选项 1,但编写查询的维护成本更高
None 这些都是很好的选择。你要的是:
- 每行一行 object
- 简单查询
- 简单架构
- 低维护
A document database, such as Elasticsearch 为您提供了开箱即用的所有这些,但是您可以通过放宽“严格性”并将整个 object 保存为 [=92 来使用关系数据库实现相同的效果=] 在单列中:
create table object (
id int, -- typically auto incrementing
-- FK to parent - see below
json text -- store object as json
);
顺便说一句,postgres 将是一个不错的选择,因为它通过 json
数据类型具有 native support for json。
我在我的职业生涯中使用过几次,每次都成功。我为 object class 类型添加了一列(在 java 上下文中):
create table object (
id int,
-- FK to parent - see below
class_name text,
json text
);
并使用 json 库将使用指定 class 的 json 反序列化为 class 的 object。无论您使用何种语言,都可以通过某种方式实现这一想法。
至于层次结构,关系数据库做得很好。来自 canvas:
create table canvas (
id int,
-- various attributes
);
如果 object 没有重复使用:
create table object (
id int,
canvas_id int not null references canvas,
class_name text,
json text,
layer int not null
);
如果 object 被重复使用:
如果 object 没有重复使用:
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
);