3

このスキーマでは:

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
);

オブジェクトには、任意の数のタグを付けることができます。オブジェクト レコードで簡単に取得できるように、テーブルの代わりにs を配列object X tagに保持したいと考えています。tag_id

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_ids の配列を列に保持し、クロス テーブルとarray_agg()

PostgresQL SQL: Converting results to arrayを使用することが提案されました。問題は、前述のように、「これは実際には個々の配列値にインデックスを付けるのではなく、配列全体にインデックスを付ける」ことです。

intarrpg のand gist(or gin) インデックスを使用することも提案されました。問題-私にとって-インデックスは標準のpgセットベースの配列演算子用であり、配列の1つの要素を見つけるために必ずしも最適化されているわけではなく、ある配列別の要素が含まれている場合、別の配列と交差しているようです-私にとっては直感に反しますサイズ的にも速度的にも、そのような広い解決策は、そのような狭い問題には正しいということです。また、拡張機能は に限定されているようであり、またはをカバーしておらず、その有用性を制限しています。intarrintint64char

4

3 に答える 3

6

標準の Postgres を使用して、任意の 1 次元配列に GIN インデックスを作成できます。
詳細はこちらのマニュアル(最後の章) にあります。

integer配列 (plain int4、 not int2orint8および noNULL値)を操作している間、提供された追加のモジュールintarrayは、より多くの演算子と、通常は優れたパフォーマンスを提供します。以下を使用してインストールします (データベースごとに 1 回)。

CREATE EXTENSION intarray;

整数配列に GIN または GIST インデックスを作成できます。マニュアルに例があります
CREATE EXTENSIONPostgreSQL 9.1 以降が必要です。古いバージョンの場合は、提供されたスクリプトを実行する必要があります。

于 2012-06-03T05:35:09.567 に答える
2

従来の解決策は、タグのテーブルと、タグとオブジェクトの間の多対多を使用することです。次に、タグ テーブルにインデックスを付け、結合を介して 1 つの select ステートメントですべてをプルできます。プログラミング モデルに満足できない場合は、地元のフレンドリーな ORM ベンダーを調べてください。

私は決して PostgreSQL の専門家ではありませんが、これは配列の適切な使用例とは思えません。

于 2012-06-03T03:15:22.663 に答える
0

これは私の回避策です。同じことを行うための 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 は、配列インデックスである新しい列「序数」を生成します。このチュートリアルも参照してください。

pg9.5+では、JSON 配列でも問題なく動作します!

 SELECT * FROM jsonb_array_elements( '[20,11,3,5]'::JSONB ) WITH ORDINALITY
于 2012-09-03T12:23:30.027 に答える