当数组不超过50个元素时,在PostgreSql中使用表而不是数组字段类型是否更好?

Flo*_*rin 21 arrays postgresql

或者更好地说:何时使用数组作为表中的字段数据类型?

哪种解决方案可以提供更好的搜

Mil*_*dev 9

我避免使用数组有两个原因:

  • 通过在一个单元格中存储多个属性值,你违反了第一个普通形式(理论上的);
  • 每次需要处理数组的各个元素时,你必须执行一些额外的,非SQL相关的处理(实际的,但是理论上的直接结果)

  • 我是承包商(建筑),没有理论上的时间.这听起来不好吗?我尊重这一点,但我做的是第一个有效的.为什么rdbms供应商提供了数据类型(对于表),如果它违反了理论? (8认同)
  • 是的,听起来很糟糕.理论的存在为工程提供了坚实的基础.SQL供应商忽视理论这一事实有很多原因 - 他们没有时间理论,他们不了解理论,他们复制竞争对手的功能等. (5认同)
  • 采取的点.我回到锤子上看见了. (2认同)
  • 我想知道数组是否适合创建需要原子更新的多对多关系。 (2认同)

mat*_*yer 6

不知道这些链接会持续多久,所以我将粘贴结果如下: http://sqlfiddle.com/#!17/55761/2

太长了;搜索表索引然后连接很快,但是将 GIN 索引(使用 gin__int_ops)添加到具有数组列的单个表中可能会更快。此外,能够匹配“一些”或少量数组值的灵活性可能是更好的选择,例如标记系统。

create table data (
    id serial primary key,
    tags int[],
    data jsonb
);

create table tags (
    id serial primary key,
    data_id int references data(id)
);

CREATE INDEX gin_tags ON data USING GIN(tags gin__int_ops); 

SET enable_seqscan to off;

with rand as (SELECT generate_series(1,100000) AS id)
insert into data (tags) select '{5}' from rand;

update data set tags = '{1}' where id = 47300;

with rand as (SELECT generate_series(1,100000) AS id)
INSERT INTO tags(data_id) select id from rand;
Run Code Online (Sandbox Code Playgroud)

跑步:

  select data.id, data.data, data.tags
  from data, tags where tags.data_id = data.id and tags.id = 47300;
Run Code Online (Sandbox Code Playgroud)

  select data.id, data.data, data.tags
  from data where data.tags && '{1}';
Run Code Online (Sandbox Code Playgroud)

产量:

Record Count: 1; Execution Time: 3ms
QUERY PLAN
Nested Loop (cost=0.58..16.63 rows=1 width=61)
-> Index Scan using tags_pkey on tags (cost=0.29..8.31 rows=1 width=4)
Index Cond: (id = 47300)
-> Index Scan using data_pkey on data (cost=0.29..8.31 rows=1 width=61)
Index Cond: (id = tags.data_id)
Run Code Online (Sandbox Code Playgroud)

Record Count: 1; Execution Time: 1ms
QUERY PLAN
Bitmap Heap Scan on data (cost=15.88..718.31 rows=500 width=61)
Recheck Cond: (tags && '{1}'::integer[])
-> Bitmap Index Scan on gin_tags (cost=0.00..15.75 rows=500 width=0)
Index Cond: (tags && '{1}'::integer[])
Run Code Online (Sandbox Code Playgroud)


Dan*_*ane 5

我也考虑了这个问题,得出的结论是,当您要消除表联接时使用数组。每个数组中包含的元素数量并不像所涉及表的大小那么重要。如果每个表中只有几千行,那么联接以获得50个子行应该不是什么大问题。如果进入10或100的数千行或数千行,则很可能会开始消耗大量的处理器时间和磁盘I / O。