2016-09-03 6 views
0

私の小さなデータベースを最適化する必要があります。遅すぎるため、別の解決策が見つかるかもしれません。データベース構造を構築する別の方法

まず、データベースに格納されているデータについて説明します。 2つのがありますオブジェクト:usersはとのはmessages

ユーザー

を言わせているようなものがあります:

+----+---------+-------+-----+ 
| id | user_id | login | etc | 
+----+---------+-------+-----+ 
| 1 | 100001 | A | ....| 
| 2 | 100002 | B | ....| 
| 3 | 100003 | C | ....| 
|... | ...... | ... | ....| 
+----+---------+-------+-----+ 

このテーブル内部には問題はありません。 (user_idは、別のアプリケーションで使用される。iduser_idを恐れていないのですか、それはここにする必要があります。)

メッセージ

そして、2番目の表は、いくつかの問題を抱えています。

+----+---------+------+----+ 
| id | user_id | from | to | 
+----+---------+------+----+ 
| 1 | 1  | aab | bbc| 
| 2 | 2  | vfd | gfg| 
| 3 | 1  | aab | bbc| 
| 4 | 1  | fge | gfg| 
| 5 | 3  | aab | gdf| 
|... | ...... | ... | ...| 
+----+---------+------+----+ 

editメッセージへの必要はありませんが、ユーザのためのメッセージの更新リストに機会があるはずです:各ユーザーは、このような例のためのメッセージを持っています。たとえば、外部サービスはすべてのユーザーのメッセージをdbに送信し、リストを更新する必要があります。 そして最も重要なことは、約30人のユーザーがおり、平均的なユーザーが500以上のメッセージを持っているということです。もう一つの問題は、フィールドfromを検索して一致数を計算しなければならないことです。私は結合で簡単なSQLクエリを設計しましたが、データを取得するには時間がかかります。

これは非常に大量のデータです。私はRDS(私はPostgreSQLを使用)を使わないことに決め、Clickhouseのようなデータベースに移動することに決めました。

しかし、私は例えばClickhouseUPDATEをサポートしていないという問題に直面しました。

この問題を解決するために、メッセージを1つの行として保存することに決めました。だから、テーブルMessagesは次のようにする必要があります:

    Here I'd like to store messages in JSON format 
       {"from":"aaa", "to":bbe"} 
       {"from":"ret", "to":fdd"} 
       {"from":"gfd", "to":dgf"} 
        ||       
        \/ 
+----+---------+----------+------+ And there I'd like to store the 
| id | user_id | messages | hash | <= hash of the messages. 
+----+---------+----------+------+ 

私はmessages塔内全文検索がようにいくつかの時間資源を節約し、と思います。

ご意見はありますか? :)

+0

あなたの質問は非常に幅広いと言わなければなりません。まず第一に、どのタイプが由来し、それもカラムですか?第二に、PostgreSQLの使用時にどのようにインデックスを使用しましたか?パーティションを調べましたか? –

+0

'from'と' to'はvarchar(255)ですが、私はパーティションを見ていません...あなたはチュートリアルを提供できますか? – Ascelhem

答えて

0

まず、大きなデータセットがある場合は、可能であればfromtoの列は比較が高速であるため、整数にする必要があります。

第2に、適切なインデックスの作成を検討する必要があります。各ユーザーのレコード数が比較的少ないため(合計30,000件に比べて500件)、パフォーマンスが大幅に向上します。

他のすべてが失敗した場合、パーティションの使用を検討:、あなたの場合は

https://www.postgresql.org/docs/9.1/static/ddl-partitioning.html

彼らはダイナミックになり、初めての妨げには非常に挿入し、そう非常に効率的な場合、私は、唯一の最後として、それらを検討しますリゾート。

2

ClickHouseでは、最適な方法はデータを「大きなフラットテーブル」に保存することです。 したがって、すべてのメッセージを別々の行に格納します。 1つのノードでも、ClickHouseでは150億行がOKです。

また、各ユーザーの属性をメッセージ表(事前結合済)に直接入れることは妥当なので、JOINを実行する必要はありません。ユーザー属性が更新されない場合に適しています。

これらの属性には、ユーザーのメッセージごとに繰り返し値が設定されます.ClickHouseはデータをよく圧縮します。

ユーザーの属性が更新されている場合は、別のデータベースにユーザーテーブルを格納し、「外部辞書」機能を使用してユーザーテーブルに追加することを検討してください。

メッセージが更新された場合は、更新しないでください。変更されたメッセージを含む別の行を代わりにテーブルに書き込み、古いメッセージをそのままにします。

テーブルの右プライマリキーを持つことが重要です。 MergeTreeファミリのテーブルを使用する必要があります。MergeTreeファミリは、主キーでデータを常に並べ替えるため、範囲クエリの効率を維持します。プライマリキーは一意である必要はありません。たとえば、「from = ...」と頻繁に書き込む場合や、これらのクエリを短時間で処理する必要がある場合は、プライマリキーをそのまま(from)として定義できます。

user_idをプライマリキーとして使用することができます:ユーザIDによるクエリが頻繁で、できるだけ早く処理する必要があるが、 'from'の述語を持つクエリはテーブル全体をスキャンします(ClickHouseがフルスキャンを効率的に行う)。

多くの異なる属性で高速検索が必要な場合は、異なる主キーを持つテーブルを複製するだけで済みます。通常、テーブルは十分に圧縮されているため、異なる範囲のクエリに対して異なる順序でいくつかのコピーでデータを持つことができます。

関連する問題