web-dev-qa-db-ja.com

配列列を使用した内部結合

O (log n)時間内にクエリのインデックス作成と実行に問題があります。

クエリには、_INNER JOIN_、_ORDER BY_、および等価演算が含まれます。データベースの法則を正しく理解している場合、非等値演算子が複数の列で使用されていなければ、クエリにインデックスを付けてO (log n)時間(またはその前後)で実行できます。この場合、_INNER JOIN_は等価演算子としてカウントされ、非等価演算子はクエリの_ORDER BY_部分になると思います。このテーブルには10,000,000以上の行があり、1秒あたり数回の読み取りと書き込みを処理する必要があります。

PostgreSQLの使用。これはテーブルがどのように見えるかです。ご覧のとおり、「Names」列はリストプロパティであり、_INNER JOIN_が対象とする列です。

_Age Names                       Date
34  ['carla', 'john', 'sam']    3/13/2011
26  ['json', 'cindy', 'joel']   3/13/2011
72  ['beth', 'amber', 'susie']  3/13/2011
14  ['john', 'jim', 'debie']    3/13/2011
_

これは私たちがやろうとしているクエリです:

_SELECT * FROM the_table WHERE Age==26 AND Names=='john' ORDER BY Date
_

私の背景はApp Engineのビッグテーブルを使用しているため、ここでは等号演算子を使用して_'john'_をNames列の名前の1つにする必要があることを示しています。これは、GAEのビッグテーブルでは許容可能なクエリです。すべてのビッグテーブルクエリが実行する必要があるため、O (log N)時間で実行されます。 PostgreSQLはリストデータ型を列として受け入れるため、PostgreSQLでもこれを行う方法があると想定しています。

これはPostgreSQLで可能ですか?

もしそうなら、どのようにインデックスを設定する必要がありますか(3つのプロパティを考慮に入れてインデックスを設定する方法を理解できません)?

4
Chris Dutrow

これは、PostgreSQL 8.4以降で可能です。複数列のGINインデックスを作成するには、追加モジュール btree_gin をインストールする必要があります。
通常、integerdateのような単純なタイプは、(デフォルトの)Bツリーインデックスを使用する方がよいため、標準のPostgreSQLにはインストールされません。ただし、このようなケースでは、複数列のインデックスが最も高速であるため、プレーンタイプには追加のインデックスメソッドが必要です。

PostgreSQL 9.1以降では CREATE EXTENSION

CREATE EXTENSION btree_gin;

古いバージョン 特権システムユーザー(postgresなど)として実行します。

psql -d dbname -f SHAREDIR/contrib/btree_gin.sql

DebianのPostgreSQL 8.4インストールの場合、これは次のようになります。

psql -d mydb -f /usr/share/postgresql/8.4/contrib/btree_gin.sql

次に、このテーブルを与えます:

CREATE TEMP TABLE tbl (age int, names text[], thedate date);

...この複数列のGINインデックスを作成できます。

CREATE INDEX tbl_gin_idx ON tbl USING GIN (names, age, thedate);

...次のようなクエリで使用できます。

SELECT * FROM tbl
WHERE  age = 26
AND    '{json}'::text[] <@ names
ORDER  BY thedate;

GINインデックスは、書き込み操作に重要なコストをもたらすことに注意してください。
しかし、インデックスのない1000万行のSELECTがあなたに何をするかと比較すると、それは言及する価値がほとんどありません。

4

あなたは試してみましたか:

SELECT * from the_table WHERE Age = 26 AND array['john'] && Names ORDER BY Date

次のようなインデックスを使用する:

CREATE INDEX the_table_idx ON the_table USING GIN (Names, Age, Date);

または少なくとも次のようなインデックス

CREATE INDEX the_table_idx ON the_table USING GIN (Names, Age);
0