簡體   English   中英

如何在PostgreSQL中為數組的元素創建索引?

[英]How to create an index for elements of an array in PostgreSQL?

使用此架構:

create table object (
   obj_id      serial      primary key,
   name        varchar(80) not null unique,
   description text,
   tag_arr     int[]
);

create table tag (
   tag_id      serial      primary key,
   label       varchar(20) not null unique
);

一個對象可以附加任何數量的標簽。 我希望將tag_id s保留在數組中,而不是object X tag表,以便可以通過對象記錄輕松獲取它們。

如何在object上創建索引,以便tar_arr每個元素都是索引?

也就是說,是否有更好的方法來解決此問題?

討論

這可以通過以下方式實現:

create table obj_x_tag(
   obj_id    references object,
   tag_id    references tag,
   constraint obj_x_tag_pk primary key( obj_id, tag_id )
);

select obj_id, name, description, array_agg( tag_id )
from object o
join obj_x_tag x using( obj_id )
group by 1, 2;

但是對我來說,將tag_id數組簡單地保留在列中並省去交叉表和array_agg()更有意義

建議使用PostgresQL SQL:將結果轉換為array 如前所述,問題是“這實際上並未索引單個數組的值,而是索引了整個數組”

還建議使用pg的intarrgist (或gin )索引。 問題-我-看來,指數是基於集合的標准PG陣列運營商,尋找一個數組的一個元素不一定是優化的,而其中一個陣列包含另一個,另一個相交 -對我來說這是反直覺在尺寸和速度方面,如此廣泛的解決方案對於如此狹窄的問題是正確的。 另外, intarr擴展似乎僅限於int ,不覆蓋int64char ,從而限制了其有用性。

您可以使用標准Postgres在任何一維數組上創建GIN索引。
手冊的詳細信息在此 (最后一章)。

當使用integer數組(普通int4 ,而不是int2int8並且沒有NULL值)進行操作時, 附加提供的模塊intarray提供了更多的運算符,並且通常具有出色的性能。 使用以下命令安裝(每個數據庫一次):

CREATE EXTENSION intarray;

您可以在整數數組上創建GIN或GIST索引。 手冊中示例。
CREATE EXTENSION需要PostgreSQL 9.1或更高版本。 對於較舊的版本,您需要運行提供的腳本。

傳統的解決方案是使用標簽表,並在標簽和對象之間使用很多表。 然后,您可以為標簽表建立索引,並通過連接在單個select語句中提取所有內容。 如果您對編程模型不滿意,請咨詢當地友好的ORM供應商。

無論如何我都不是PostgreSQL專家,但這似乎不是數組的好用例。

這是我的解決方法,因為我認為沒有PostgreSQL優化的內部函數可以執行相同的操作,

CREATE FUNCTION unnest_with_idx(anyarray) RETURNS 
table(idx integer, val anyelement) AS $$ 
   SELECT generate_series(1,array_upper($1,1)) as idx, unnest($1) as val;
$$ LANGUAGE SQL IMMUTABLE;
-- Test:
SELECT idx,val from unnest_with_idx(array[1,20,3,5]) as t;

要檢查是否存在內部函數,請參閱“ 如何使用postgreSQL訪問數組內部索引? ”問題。


@JimNasby評論后編輯

pg9.4 +的解決方案

SELECT * FROM unnest(array[20,11,3,5]) WITH ORDINALITY;

WITH ORDINALITY會產生一個新的列“ ordinality”,即數組索引。 另請參閱本教程

pg9.5 +中 ,它也可以用於JSON數組!

 SELECT * FROM jsonb_array_elements( '[20,11,3,5]'::JSONB ) WITH ORDINALITY

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM