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

use*_*402 16 arrays postgresql performance join bigdata

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

表名为"Item"
服务器为:12 GB RAM,1,5 TB SATA,4 CORES.postgres的所有服务器.
此数据库中有更多表,因此RAM不包括所有数据库.

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

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

select * from item where ...... and '{5}' <@ a_elements;
Run Code Online (Sandbox Code Playgroud)

我还有第二个,更经典的选择.

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

  • id_item
  • id_element

该表将有大约200万条记录.

我能够对这些表进行分区,因此表元素中的记录数将减少到20万,表项中减少500 K.

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

select item.* 
from item 
    left join elements on (item.id_item=elements.id_item) 
where .... 
and 5 = elements.id_element
Run Code Online (Sandbox Code Playgroud)

我想知道在性能方面哪种选择会更好.postgres能够在单个查询中使用索引GIN(选项1)的许多不同索引吗?

我需要做出一个好的决定,因为导入这些数据需要20天.

Tom*_*zky 12

我想你应该用一张elements桌子:

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

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

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

但我已经为10M元素做了一些测试:

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
Run Code Online (Sandbox Code Playgroud)

所以另一方面,数组较小,索引较小.在做出决定之前,我会做200M元素测试.