この問題は、しばらく頭痛を引き起こしています。 PostgreSQL 8.4データベースは、4.000.000を超えるレコードを含む1つのテーブルのみで構成されています。この表は以下のように構成されています。ボックス間の距離を決定する
CREATE TABLE metadata (
id serial NOT NULL,
"value" text NOT NULL DEFAULT ''::text,
segment_box box NOT NULL DEFAULT box(point(((-9223372036854775808)::bigint)::double precision, (1)::double precision), point((9223372036854775807::bigint)::double precision, ((-1))::double precision)),
CONSTRAINT metadata_pk PRIMARY KEY (id)
)
CREATE INDEX metadata_segment_box_ix
ON metadata
USING gist
(segment_box);
CREATE INDEX metadata_tag_value_ix
ON metadata
USING btree
(value);
表には、長方形のボックスで表されるセグメントが含まれています。これらのセグメントには、「値」列を使用して注釈が付けられます。
データベースで実行したいクエリの種類は、特定のウィンドウ内に含まれる指定された値を持つすべてのセグメントを検索しようとします。
SELECT * FROM (SELECT * FROM metadata WHERE value='X') a,
(SELECT * FROM metadata WHERE AND value='Y') b
WHERE a.segment_box <-> b.segment_box <= 3000
しかし、おそらく気づいたように、このクエリはデータベースによって効率的に実行できません。サブクエリaとbのデカルト積は本当に大きくなっています。これらのクエリをより効率的に実行する方法はありますか?私は、スライディングウィンドウのアプローチのいくつかの並べ替えがトリックを行うだろうと想像することができます。次のような多分何か:
SELECT *, rank() OVER (
PARTITION BY "value" ORDER BY (segment_box[1])[0], (segment_box[0])[0]
) FROM metadata WHERE value='X' OR value='Y'
アップデート:私はPostgresのでカスタム関数を作成して、この質問を投稿した後に試したことの ひとつ。私は試しました:
CREATE OR REPLACE FUNCTION within_window(size bigint DEFAULT 0)
RETURNS setof metadata AS
$BODY$DECLARE
segment RECORD;
neighbour RECORD;
newwindow box;
BEGIN
FOR segment IN (
SELECT * FROM metadata WHERE value='X' OR value='Y'
ORDER BY (segment_box[1])[0], (segment_box[0])[0]
) LOOP
newwindow := box(segment.segment_box[0],
point((((segment.segment_box[1])[0]) + size), (segment.segment_box[1])[1]));
FOR neighbour IN (
SELECT DISTINCT ON (metadata_id) * FROM metadata WHERE value='X' OR value='Y')
AND segment_box &< newwindow
AND segment_box &> newwindow
) LOOP
RETURN NEXT neighbour;
END LOOP;
END LOOP;
END;$BODY$
LANGUAGE plpgsql;
しかし、この機能は、何度も実行する必要があるサブクエリのため、上記の基本的な解決策と同じくらい遅いです。これについての他の考え?
質問には「postgis」というタグがありますが、ここではPostGISを使用していません。そうした場合、[ST_DWithin](http://postgis.org/documentation/manual-svn/ST_DWithin.html)のような優れたバッファー的な機能が役立ちます。 –
ST_DWithin関数を使用すると、回答に表示されている関数と比べてクエリがさらに高速になると思いますか? – joost1024