大量 (~500 万) のインデックス付きデータ ポイントを含む一連のオブジェクト (~1000 行) を効率的に順序付けする方法を見つけようとすると、難しい問題があります。私の場合、特定のデータポイントでテーブルを並べ替えることができるクエリが必要です。各データポイントは 16 ビットの符号なし整数です。
私は現在、大きな配列を使用してこの問題を解決しています:
オブジェクト テーブル:
id serial NOT NULL,
category_id integer,
description text,
name character varying(255),
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL,
data integer[],
GIST インデックス:
CREATE INDEX object_rdtree_idx
ON object
USING gist
(data gist__intbig_ops)
このインデックスは現在、選択クエリを実行するときに使用されていませんが、とにかく役立つかどうかはわかりません。
配列フィールドは毎日、約 500 万個の値の新しいセットで更新されます
特定のデータ ポイントの値で並べ替えられたすべてのオブジェクトを一覧表示する必要がある Web サーバーがあります。
クエリの例:
SELECT name, data[3916863] as weight FROM object ORDER BY weight DESC
現在、このクエリの実行には約 2.5 秒かかります。
質問: より良いアプローチはありますか? 挿入側がバックグラウンドで発生するので遅くなるのはうれしいですが、選択クエリはできるだけ速くする必要があります。とは言っても挿入にかかる時間には限界があります。
すべての値に独自の行があるルックアップ テーブルを作成することを検討しましたが、挿入/ルックアップ時間がこのアプローチによってどのように影響を受けるかはわかりません。個々の行として最大 500 万のデータ ポイントを持つ 1000 以上のレコードを入力すると思われます。遅すぎる。
現在、行の挿入には約 30 秒かかりますが、現時点では許容範囲です。
最終的には、基本的な問題に対するスケーラブルなソリューションを探していますが、今のところ、このソリューションが機能する必要があるため、このソリューションをさらにスケールアップする必要はありません。
更新: 配列の代わりに巨大なテーブルを使用することを却下したのは間違いでした。挿入時間は大幅に増加しましたが、クエリ時間はわずか数ミリ秒に短縮されました。
データムがゼロ以外で前回の更新から変更された場合にのみデータムを保存するように生成アルゴリズムを変更しています。これにより、数秒しかかからない数十万の値に挿入が削減されました。
新しいテーブル:
CREATE TABLE data
(
object_id integer,
data_index integer,
value integer,
)
CREATE INDEX index_data_on_data_index
ON data
USING btree
("data_index");
新しいクエリ:
SELECT name, coalesce(value,0) as weight FROM objects LEFT OUTER JOIN data on data.object_id = objects.id AND data_index = 7731363 ORDER BY weight DESC
挿入時間: 15,000 レコード/秒
クエリ時間: 17ms