8

Redisは、私が使用している従来のSQLデータベースとは概念的に異なり、自分のプロジェクトに適しているかどうかを判断しようとしています...周りを見回していますが、質問に対する答えが見つからないようです。

保存する必要のあるユーザーのセットがあり、それぞれに一意のIDといくつかの値(名前など)が関連付けられています。それらをハッシュとして簡単に保存できるようです。

user:fef982dcfe1a7bcba4849b4c281bba95
"username" "andrewm" "name" "Andrew"

保存したいメッセージもたくさんあり、それぞれに送信者や受信者などのいくつかのプロパティがあります。

message:1a7bcba4849b4c281bfef98a952dcfeb
"sender" "fef982dcfe1a7bcba4849b4c281bba95" "recipient" "82dcfe1a7bcba4849b4c281bba95fef9" "message" "Hi!"

私の質問は、特定のユーザー(ハッシュで指定)によって送信されたすべてのメッセージを取得するにはどうすればよいかということです。代わりに、従来のリレーショナルデータベースを使用する必要がありますか、それともMongoDB(以前に使用したもの)のようなNoSQLデータベースを使用する必要がありますか?もしそうなら、誰かが高性能店のための提案がありますか?私は真の検索(つまり、MySQLLIKEクエリ)を実行しません。実際には、キー値のルックアップだけを実行します。

4

2 に答える 2

11

これらのデータをRedisでモデル化することは確かに可能ですが、データ構造とアクセスパスの観点から考える必要があります。Redisを使用すると、アクセスパスは暗黙的に管理されません(RDBMS / MongoDBのインデックスの場合のように)。

提供されている例では、次のようになります。

user:<user hash> -> hash of user properties
user:<user hash>:sent -> set of <msg hash>
user:<user hash>:received -> set of <msg hash>
message:<msg hash> -> hash of message properties

メッセージの追加/削除は、メッセージオブジェクト自体の追加/削除に加えて、送信者と受信者に対応する*:sentセットと*:receivedセットを維持することを意味します。

特定のユーザーの送受信メッセージを取得するのは、SMEMBERSコマンド、またはメッセージのプロパティも同時に取得する場合はSORTです。

# Get a list of message hash codes only in one roundtrip
smembers user:<user hash>:received

# Get a list of message contents in one roundtrip
sort user:<user hash>:received by nosort get message:*->sender get message:*->message

ソートを使用する理由については、以下を参照してください。

注1: Redisでは、整数はより効率的な方法で保存されるため、UUIDやハッシュコード(特にセット内)ではなく、整数をキーとして使用することをお勧めします。

注2:メッセージを注文する必要がある場合は、セットの代わりにリストを使用する必要があります。その結果、削除できるのは最も古いメッセージのみであり、効率的な方法で追加できるのは新しいセットのメッセージのみです。おそらく、すべてのメッセージのグローバルリストも追加するでしょう。

于 2012-07-01T09:32:37.003 に答える
1

Redisの基本データ型は、マルチ条件クエリ、全文検索などをサポートしていません。そのため、Redisソースコードを変更し、補助インデックスを介してSQLデータのように使用できるデータベースにRedisを変換しました。

このプロジェクトのホームページはhttps://oncedb.comです。

OnceDBはRedisのデータストレージ構造を変更しません。RedisデータベースファイルはOnceDBで直接操作してから、Redisに返して使用することができます。

インデックス検索

インデックスを作成する

全文検索のパフォーマンスは低くなります。インデックスを作成することでパフォーマンスを向上させることができます。この方法では、インデックス付きフィールドの順序付きリストを作成し、条件付きクエリの実行時にこれらの順序付きリストに対して交差クエリ操作を実行します。

# Create hash data
hmset article:001 poster dota visit 21 key js
hmset article:002 poster dota visit 11 key c
hmset article:003 poster like visit 34 key js
hmset article:004 poster like visit 44 key c

次に、上記のフィールドのインデックスを作成します。重みスコアは次のように設定されます。202000201、時間に関する整数。値は記事のID値です。

# Create indexed
zadd *article.poster:dota 20200201 001 20200201 002
zadd *article.poster:like 20200201 003 20200201 004
zadd *article.key:js 20200201 001 20200201 003
zadd *article.key:c 20200201 002 20200201 004
# "visit" using its value as the weight score
zadd *article.visit 21 001 11 002 34 003 44 004

インデックスによるクエリ

2つのインデックス*article.key:jsと* article.poster:dotaの共通部分を見つけて、それらを*tmp1順序付きリストに格納します。

zinterstore *tmp1 2 *article.key:js *article.poster:dota
> 1

次に、* tmp1は、key=jsおよびposter=dotaの条件を満たすIDセットを格納します。

zrange *tmp1 0 -1
> 001

zrangehmgetコマンドを使用して、対応するHASH値を出力できます。

zrangehmget *tmp1 0 -1 article: key poster
1) 001
2) 40400402
3) js
4) dota
5) 
6) 

結果は、直接全文検索キー=jsおよびposter=dotaと同じです。

hsearch article:* key = js poster = dota
1) article:001
2) js
3) dota

検索範囲

たとえば、訪問数が20〜30で、key = jsのデータを検索するには、重みを制御することでデータを検索できます。

一時的なインデックスを作成し、*article.visitの重みとkey=jsのデータのみを取得します

zinterstore *tmp2 2 *article.key:js *article.visit weights 0 1
> 2

20〜30のデータを取得します

zrangebyscore *tmp2 20 30
> 001

zrangehmgetbyscoreを使用して、対応するハッシュデータを出力できます。

zrangehmgetbyscore *tmp2 20 30 article: key visit
1) 001
2) 21
3) js
4) 21
5) 
6) 

結果は、全文検索を使用した結果と一致しています。

hsearch article:* visit >= 20 visit <= 30 key = js
1) article:001
2) 21
3) 
4) js

同一のフィールドが2つあるため、visit> = 20 visit <= 30の場合、検索結果には1つしか出力されず、3行目の繰り返しフィールドには空が出力されます。

その他のOnceDB拡張命令を表示できます:OnceDBでの命令の検索、クエリ、計算、および合計

自動インデックス作成

Redisインデックスの作成と保守はあまり便利ではありません。OnceDBは、データが変更されたときに補助インデックスを自動的に作成することを選択できます。

インデックスの作成:スキーマフィールドの演算子値をアップサート..。

upsert / insert / updateディレクティブと特殊演算子を使用して、インデックスを自動的に作成します。

上記の例は次のように書くことができます:

upsert article id @ 001 poster ? dota visit / 21 key ? js
upsert article id @ 002 poster ? dota visit / 11 key ? c
upsert article id @ 003 poster ? like visit / 34 key ? js
upsert article id @ 004 poster ? like visit / 44 key ? c

オペレーター:

@:主キー?:グループインデックス/:ソートインデックス

インデックスは、操作後に自動的に作成されます。* article * article.poster:dota * article.poster:like * article.visit * article.key:js * article.key:c

マルチコンディションインデックスクエリ:スキーマを検索してからフィールドオペレータ値まで..。

インデックスのあるフィールドの場合、findコマンドを使用してインデックスフィールドをクエリできます。たとえば、クエリ:key=jsおよびposter=dotaのデータ。「?」が使えます これらの2つのフィールドがグループ化されたインデックスであることを示すには:

find article 0 -1 key ? js poster ? dota
1) 1
2) article:001
3) js
4) dota

1はデータの総量を表します。-1の場合は、全文検索が使用されており、パフォーマンスが低下していることを意味します。

インデックス範囲クエリ

@を追加してインデックス範囲を指定し、+を使用してスコアの重み範囲に使用するインデックスフィールドを指定できます。

find article 0@20 -1@30 key ? js visit /+ *
1) 1
2) article:001
3) js
4) 21

インデックスを削除

OnceDBはインデックス定義を保存しません。削除するときは、どのフィールドにインデックスが含まれているかを手動で指定する必要があります。フィールド名とインデックス演算子を指定する必要があります。

remove article @ 001 key ? poster ? visit /

インデックス名とウェイトスコアをカスタマイズすることもできます。詳細な手順については、「OnceDBデータの変更とクエリのヘルプドキュメント」を参照してください。

于 2020-02-01T10:08:36.780 に答える