2012-08-03 17 views
13

假設我們有一個包含600萬條記錄的表。有16個整數列和幾個文本列。它是隻讀表,因此每個整數列都有一個索引。 每個記錄大約50-60個字節。Postgresql - 在大數據庫中使用數組的性能

表名是「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; 

我也有第二個,更經典,選項。

不要用兩列列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 

我不知道什麼選擇是在性能上來看比較好。 是否可以在單個查詢中使用帶索引GIN(選項1)的許多不同索引?

我需要做出正確的決定,因爲導入這些數據需要20天。

+1

嗨!你最後的決定是什麼?我有幾乎相同的情況。 – 2015-03-17 06:42:17

回答

10

我認爲你應該使用一個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元素測試。