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

oxf4rvwz  于 2023-10-18  发布在  PostgreSQL
关注(0)|答案(6)|浏览(114)

或者更好地说:什么时候使用数组作为表中的字段数据类型?
哪种解决方案提供更好的搜索结果?

vvppvyoh

vvppvyoh1#

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

  • 通过在单元格中存储多个属性值,您违反了第一范式(理论);
  • 每次需要处理数组的单个元素时,都必须执行一些额外的、与SQL无关的处理(实际上,但这是理论上的直接结果)
rggaifut

rggaifut2#

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

htrmnn0y

htrmnn0y3#

不知道多久这些链接保持住,所以我会粘贴下面的结果: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;

跑步:

select data.id, data.data, data.tags
  from data, tags where tags.data_id = data.id and tags.id = 47300;

select data.id, data.data, data.tags
  from data where data.tags && '{1}';

产量:

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)

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[])
xxhby3vn

xxhby3vn4#

假设您在实际数组中查询某些内容,这些表将始终提供更好的搜索结果。对于子表,可以对内容进行简单的索引,而对于数组,则必须创建50个索引(每个索引对应数组中的每个潜在元素)。

shstlldc

shstlldc5#

我认为数组必须用于一些自定义数据。但对于外键-最好使用链表(或其他东西,但每个键列)。这样你就可以在数据库级别进行数据控制,并且可以轻松地进行连接查询--即使你在数组中有连接(对于完整的数据集),你也需要连接--但是数组比“标准”SQL复杂得多。P.S.抱歉英语不好

egmofgnx

egmofgnx6#

我知道这篇文章是15岁在这一点上,但它是我的顶部谷歌结果,所以我想我会插话。
和往常一样,这取决于你的数据分布是什么样的,以及你的查询是什么样的。数组出现的一个常见用例是标签(想想哈希标签等)。这篇文章也是用[数组]和[postgresql]标记的。标签通常具有相当重的尾部分布(少数标签占绝大多数)。对于这种类型的数据,除非你只是计算标签,否则你几乎总是更好地使用字符串数组。基本原理是,大多数时候您可能关心与单个文档相关联的标记。
database soup上有一个很棒的帖子。结论是:

  • 总赢家是一个文本数组,带有GIN索引。这对于单标签搜索更好,对于双标签搜索更快,并且在其他任务中具有竞争力。它也是最小的表示形式,如果您将标记数组放入documents表中,它会变得更小、更快。尽管如此,有时您还是希望使用带有纯文本标记的传统子表:如果你构建了很多标签云,或者你从来没有搜索过两个标签,而你的ORM不能处理Postgres数组。

相关问题