Ответ 1
Я думаю, вы должны использовать таблицу 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
Таким образом, с другой стороны массивы меньше и имеют меньший индекс. Я бы сделал несколько тестов на 200M элементов, прежде чем принимать решение.