arrays - Postgresql - 在大数据库中使用数组的性能

标签 arrays performance postgresql join bigdata

假设我们有一个包含 600 万条记录的表。有 16 个整数列和少量文本列。它是只读表,因此每个整数列都有一个索引。 每条记录大约 50-60 字节。

表名为“Item”
服务器是:12 GB RAM,1.5 TB SATA,4 核。 postgres 的所有服务器。
此数据库中有更多表,因此 RAM 不会覆盖所有数据库。

我想在表“Item”中添加一列“a_elements”(大整数数组类型) 每条记录在此列中的元素不会超过 50-60 个。

之后,我将在此列上创建索引 GIN,典型的查询应如下所示:

select * from item where ...... and '{5}' <@ a_elements;

我还有第二个更经典的选项。

不将列 a_elements 添加到表项,而是创建具有两列的表元素:

  • id_item
  • id_元素

这个表将有大约 2 亿条记录。

我能够对该表进行分区,因此表元素中的记录数将减少到 2000 万条,表项中的记录数将减少到 500K。

第二个选项查询如下所示:

select item.* 
from item 
    left join elements on (item.id_item=elements.id_item) 
where .... 
and 5 = elements.id_element

我想知道从性能的角度来看哪个选项会更好。 postgres 是否能够在单个查询中使用索引 GIN(选项 1)的许多不同索引?

我需要做出明智的决定,因为导入这些数据需要 20 天时间。

最佳答案

我认为你应该使用 elements 表:

  • Postgres 将能够使用统计信息来预测在执行查询之前将匹配多少行,因此它将能够使用最佳查询计划(如果您的数据分布不均则更为重要);

  • 您将能够使用 CLUSTER elements USING elements_id_element_idx 来本地化查询数据;

  • 当 Postgres 9.2 发布时,您将能够利用仅索引扫描;

但是我已经对 1000 万个元素进行了一些测试:

create table elements (id_item bigint, id_element bigint);
insert into elements
  select (random()*524288)::int, (random()*32768)::int
    from generate_series(1,10000000);

\timing
create index elements_id_item on elements(id_item);
Time: 15470,685 ms
create index elements_id_element on elements(id_element);
Time: 15121,090 ms

select relation, pg_size_pretty(pg_relation_size(relation))
  from (
    select unnest(array['elements','elements_id_item', 'elements_id_element'])
      as relation
  ) as _;
      relation       | pg_size_pretty 
---------------------+----------------
 elements            | 422 MB
 elements_id_item    | 214 MB
 elements_id_element | 214 MB



create table arrays (id_item bigint, a_elements bigint[]);
insert into arrays select array_agg(id_element) from elements group by id_item;

create index arrays_a_elements_idx on arrays using gin (a_elements);
Time: 22102,700 ms

select relation, pg_size_pretty(pg_relation_size(relation))
  from (
    select unnest(array['arrays','arrays_a_elements_idx']) as relation
  ) as _;
       relation        | pg_size_pretty 
-----------------------+----------------
 arrays                | 108 MB
 arrays_a_elements_idx | 73 MB

所以另一方面,数组更小,索引也更小。在做出决定之前,我会进行一些 200M 元素测试。

关于arrays - Postgresql - 在大数据库中使用数组的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11791698/

相关文章:

postgresql - SQL (PostgreSQL) : How to write a query to fetch the average salary of top 100 highest paid employees?

sql - Postgres 选择所有列,但按一列分组

C#单例实现性能

sql - 使用复杂的双连接来获取子对象的数量

c++ - 指向对象数组中函数的指针数组

javascript - 在 JavaScript 中将数据构建到多维数组中

javascript - 如何减少 0(n) 以找到求和特定值的对的第一个实例

c - c程序中for循环中的指针

arrays - 在并行化期间在 Chapel 中使用同步变量时遇到问题

c - 在 C 中存储未知迭代次数的 while 循环的结果