19

postgreSQLデータベースを使用する必要があり、現在のberkeleyDBの使用に取って代わります。それでも; これは理想的な状況ではなく、私の手に負えない状況だと思います。

だから問題は...postgreSQLをキーバリューストアにする必要がある場合、可能な限り効率的にしながら、これをどのように行うのでしょうか?

私の値はバイト配列であり、私のキーは文字列です。これらの文字列の長さにいくつかの制限を課すことができます。

値とキーを保持する主キー列にblobを使用する必要があると思いますが、この旅に出たばかりなので、スタックオーバーフローコミュニティの誰かがこれを行ったかどうか、または特定の「落とし穴」があるかどうかに興味があります気をつけるべきです。

4

5 に答える 5

27

これを適切に行うためのPostgresqlの拡張機能はhstoreと呼ばれます。他のKey-Valueストアシステムと同じように機能します。拡張機能をロードするだけです。構文は一意ですが、redisまたはmongoを使用したことがある場合は、すぐに使用できます。それよりも難しくしないでください。私は理解しています、私たちはしばしば私たちのツールを選ぶことができず、やらなければなりません。
ドキュメントページは次のとおりです。

http://www.postgresql.org/docs/9.1/static/hstore.html

于 2012-05-29T02:19:23.670 に答える
4

もう1つのオプションは、キーに一意のハッシュインデックスを持つJSONまたはJSONBを使用することです。

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

CREATE TABLE key_values (
    key uuid DEFAULT uuid_generate_v4(),
    value jsonb
);

CREATE INDEX idx_key_values ON key_values USING hash (key);

いくつかのクエリ

SELECT * FROM key_values WHERE key = '1cfc4dbf-a1b9-46b3-8c15-a03f51dde891';
Time: 0.514 ms
postgres=# SELECT * FROM key_values WHERE key = '1cfc4dbf-a1b9-46b3-8c15-a03f51dde890';
Time: 1.747 ms

postgres=# do $$
begin
for r in 1..1000 loop
INSERT INTO key_values (value)
VALUES ('{"somelarge_json": "bla"}');
end loop;
end;
$$;
DO
Time: 58.327 ms

Bツリーのように効率的な範囲クエリを実行することはできませんが、読み取り/書き込みのパフォーマンスが向上するはずです。インデックスは約60%小さくする必要があります。

于 2019-11-27T14:04:30.213 に答える
3

リレーショナルデータベースを使用せざるを得ない場合は、非構造化データとKey-Valueストアで得られる速度の利点を放棄するため、事実を利用するためにデータ内の構造を見つけることをお勧めします。構造が多ければ多いほど、苦境から抜け出すことができます。キーの構造だけを見つけたとしても。

また、データへのシーケンシャルアクセスまたはランダムアクセスのみが必要かどうか、およびこの要件に従ってデータベースをどの比率で構造化するかについても検討してください。たとえば、タイプごとに値に対してクエリを実行しますか?これらの質問はそれぞれ、データベースの構造に影響を与える可能性があります。

postgresqlのblobに関する1つの特定の考慮事項は、内部的にpg_largetable(loid:oid、pageno:int4、data:bytea)として表されます。チャンクのサイズはLOBBLKSIZEによって定義されますが、通常は2kです。したがって、BLOBの代わりにテーブルでバイト配列を使用し、値とキーのペアのサイズをブロックサイズに制限できる場合は、2番目のテーブルを介したこの間接参照を回避できます。データベースの構成にアクセスできる場合は、ブロックサイズを増やすこともできます。

データの構造とデータアクセスのパターンを探してから、もう一度詳細に質問することをお勧めします。

于 2010-01-05T19:26:26.753 に答える
0

値として何を保存する必要がありますか?文字列?Ints?オブジェクト(シリアル化されたJavaオブジェクトなど)。単純な実装は、次のような3列のテーブルで機能します。

NAME(VARCHAR)   TYPE(VARCHAR)   VALUE(VARCHAR)

(おそらく、TYPEはいくつかの列挙です)。上記は、シリアル化されたオブジェクトのようなバイナリデータでは機能しませんが、おそらくそこにBLOBが必要です。

あるいは(そしておそらくもっと良いアイデアですが)、Apache Commons Configurationを見たことがありますか?データベースを使用して(JDBCを介して)これをバックアップし、次のようにプロパティを取得するようにプロパティを格納できます。

// get a property called 'number'
Double double = config.getDouble("number");
Integer integer = config.getInteger("number");

それはあなたに実装の面であなたに多くの悲しみを救うかもしれません。挿入および取得後にシリアル化する必要があるという点で、バイナリデータの保存に問題がある可能性があります。しかし、私は過去にこれをXStreamを介してint、double、およびシリアル化されたJavaオブジェクトを格納するために使用したので、うまく機能することを確認できます。

于 2010-01-05T19:15:34.707 に答える
0

それは本当にキーが何であるかに依存する必要があります。常に255文字未満の文字列になる場合は、Varcharをyoru PKとして使用し、値にblob(大きな値を想定)を使用します。常に数値になる場合は、intなどを使用します。

言い換えれば、本当にあなたに良い答えを与えるためにもっと多くの情報が必要です:)

于 2010-01-05T19:17:01.130 に答える