Tarantoolは、 Mail.Ruによって開発された優れた高性能のno-Sqlソリューションです。 ソースコード
このソリューションでは、キー/値モードと、1つ以上の基準(検索フィールド)に従ってレコードセット内の多数のレコードを選択することの両方を使用できます。 RuNetのアナログだけでなく、私はまだ会っていません。 ストレッチで、大根を比較できます。 しかし、大根では-データを一覧表示し、キーで選択することはできません。 開発者の主張から判断すると、キーアクセス速度はmemcacheよりも高速ですが、バックドアデータは常にディスクに保存されます。 しかし、残念なことに、この開発にはデータにアクセスするための単一のperlクライアントがあります。そのため、たとえばredisやmemcacheなどの人気はありません。
doc / box-protocolのソースには、CおよびPHPでクライアントを作成するために現在改訂しているプロトコルの説明があります。 プロトコルを勉強したら、お好みの言語でネイティブクライアントを実装できます。 この記事がこの記事でお役に立てば幸いです。
このデータベース内のすべてのデータは名前空間に分割されます。ほとんどの場合、MySQLのデータベースに類似しています。 すべての名前空間の番号はデジタルです(0、1、2など)。 各ネームスペースは、特定のインデックスでオーバーレイできます。 インデックス作成もデジタルです。 インデックスは1つまたは複数のフィールドに重ねられます。 インデックスは、HASHまたはTREEタイプにすることができます
すべてのインデックスとネームスペースは構成に登録されます。 以下に例を示します。ここでは、デジタルと文字の2つのインデックスが記述されています。 さらに、2番目のインデックスは複合です。
namespace[0].enabled = 1
namespace[0].index[0].type = "HASH"
namespace[0].index[0].unique = 1
namespace[0].index[0].key_field[0].fieldno = 0
namespace[0].index[0].key_field[0].type = "NUM"
namespace[0].index[0].key_field[1].fieldno = 1
namespace[0].index[1].type = "TREE"
namespace[0].index[1].key_field[0].fieldno = 0
namespace[0].index[1].key_field[0].type = "STR"
namespace[0].index[1].key_field[1].fieldno = 1
namespace[0].enabled = 1
namespace[0].index[0].type = "HASH"
namespace[0].index[0].unique = 1
namespace[0].index[0].key_field[0].fieldno = 0
namespace[0].index[0].key_field[0].type = "NUM"
namespace[0].index[0].key_field[1].fieldno = 1
namespace[0].index[1].type = "TREE"
namespace[0].index[1].key_field[0].fieldno = 0
namespace[0].index[1].key_field[0].type = "STR"
namespace[0].index[1].key_field[1].fieldno = 1
キーについて注意する必要があります。 キーは、デジタル(1,2,3 ... 6.2 * 10 ^ 9)またはシンボリックです。
名前空間内のすべてのデータはタプルとして保存されます。 カートはフィールドのセットです。 フィールドは、デジタルまたはシンボリックのいずれかです。
クライアントとサーバー間の交換は、メッセージによって実行されます。 tarantoolプロトコルのすべてのメッセージは、要求要求と応答に分けられます。 各メッセージには必須のヘッダーヘッダーがあり、本文も含まれる場合があります。
メッセージヘッダーには、メッセージタイプ、本文の長さ、およびリクエスト識別子が含まれます。
ヘッダー構造:
<blockquote> typedef struct { uint32_tタイプ; uint32_t len; uint32_t request_id; }ヘッダー; </ blockquote>
以下のメッセージタイプが定義されています。
0xdを挿入(13)
SELECT 0x11(17)
更新0x13(19)
DELETE 0x14(29)
PING 0xff 0xff 0x0 0x0(65280)
要求識別子はクライアントによって設定され、ゼロの場合があります。
リクエストの一般的な構造:
typedef struct { ヘッダーヘッダー ユニオン{ InsertRequest insert; SelectRequest select; UpdateRequest insert; DeleteRequest insert; }; }リクエスト;
PINGコマンドには本文がないため、PingRequestはありません;)
INSERTコマンドの本文は、操作が実行されるネームスペース番号、フラグ、およびタプルで構成されます。
名前空間-これは、タプルが保存されるスペースです。 名前空間の番号はデジタルです。 各ネームスペースで、インデックスを定義できます。 プライマリインデックス(PRIMARY)は
出席する必要があります。 インデックスは構成ファイルで定義されます。
現在、応答本文でデータを返すかどうかを示す単一のフラグBOX_RETURN_TUPLE(0x01)のみが定義されています。
INSERTリクエストの構造:
typedef struct { uint32_t namespaceNo; uint32_tフラグ; タプルタプル; } InsertRequest;
すべてのデータは、タプルタプルを使用して記述されます。 タプルは、タプルの次元(フィールドの数)とフィールドの配列であるカーディナリティフィールドで構成されます。 一般的には、次のようになります。
typedef struct { uint32_tカード。 フィールドフィールド[]; }タプル;
各フィールドは、バイトの配列で表されます。 フィールドには、int32、int64、またはバイトストリームを含めることができます。
現在、私はそのように定義しています:
typedefフィールドu_char * data;
すべてのフィールドデータは、LED128 en.wikipedia.org/wiki/LEB128を使用してパッケージ化されます
SELECT要求の本文には、名前空間番号、サンプリングが発生するインデックス番号、オフセットオフセットと出力サイズ制限、およびタプルの数とタプル自体が含まれます。 オフセットおよび制限パラメーターは、選択に似ています:SELECT * FROM ... LIMIT
typedef struct { uint32_t namespaceNo; uint32_t indexNo; uint32_tオフセット; uint32_t制限; uint32_tカウント; タプルタプル[]; } SelectRequest;
SELECT * FROM t0 WHERE k0 = 1を指定する場合、タプルの数= 1およびタプル値は1に対応する必要があります。セカンダリ複合インデックスk1(デジタルフィールドと文字フィールド)が定義されている場合、クエリ
SELECT * FROM t0 WHERE k1 =(21、 'USSR')
タプル数= 2で、2つのタプル値を表す必要があります。 提示されたsqlは概略図であり、SQL'92標準に準拠していないことを明確にする必要があります。 実際、tarantool / boxのデータは、テーブル(列と行)ではなくタプルで表されます。 タプルには、任意の数のフィールドを含めることができます。 すべてのタプルは非スペースに保存されます。 ただし、memspaceでは、検索を実行するHASHまたはrbTREEインデックスを設定できます。
UPDATE要求の本文には、名前空間番号、フラグ、タプル、操作の数、および操作自体が含まれます。 フラグとタプルのフィールドは、UPDATE操作に似ています。 操作の数はゼロに等しくすることができます。 構造は次のようになります。
typedef struct { uint32_t namespaceNo; uint32_tフラグ; タプルタプル; int32_tカウント; 操作操作[]; } UpdateRequest;
各操作は、操作が実行されるフィールドの番号、操作コード、および引数を含む構造です。
次の操作コードが使用されます。
0-このフィールドへの引数の割り当て。
引数がint32型の場合、次のアクションも可能です。
1-既存のフィールドに引数を追加します
2-既存のフィールドでANDを実行します
3-既存のフィールドでXORを実行する
4-既存のフィールドでORを実行する
typedef struct { int32_t fieldNo; int8_tオペコード; フィールド引数。 }操作;
DELETE操作は常に主キーで実行され、名前空間番号とタプルが含まれます。 DELETE操作の構造は次のとおりです。
typedef struct { uint32_t namespaceNo; タプルタプル; } SelectRequest;
各サーバー応答には、ヘッダーヘッダー、応答コード、および必要に応じて応答本文が含まれます。 応答ヘッダー-要求ヘッダーに似ています。 戻りコード0-成功、またはinclude / iproto.hのエラーを参照
一般に、次の応答構造が取得されます。
typedef struct { ヘッダーヘッダー int32_tコード; ユニオン{ SelectResponce selectBody; insertResponce insertBody; uint8_t *データ; int32_tカウント; }; }応答;
SELECTクエリに対する応答の本文は、タプルの総数と返されたタプルのセットを含むフィールドで構成されます。 クエリ結果が空の場合、タプルは返されず、数量フィールドにはゼロが含まれます。
typedef struct { int32_tカウント; FqTupleタプル[]; } SelectResponce;
返された各タプル(FqTuple)には、タプルのサイズ、いくつかの識別カーディナリティーが含まれ、セパレーター(境界)およびタプル自体として機能します。
typedef struct { int32_tサイズ; uint32_tカード。 タプルタプル; } FqTuple;
InsertRequest要求でBOX_RETURN_TUPLEフラグが設定されている場合、応答には本文が含まれる場合があります。
typedef struct { int32_tカウント; FqTupleタプル; } InsertResponce;
UPDATEクエリへの応答も同様です。
削除クエリは、削除されたレコードの数を返します。 削除中はプライマリインデックスのみが使用されるため、それぞれ1つのレコードのみを削除でき、0または1を返します。これは、Responce構造のカウントフィールドです。 構造内でも、データ分析のためにデータバイトの配列が割り当てられます。
テキストにはいくつかの不正確さがあり、どこかでuint32_tの代わりにint32_tを使用できます。
おそらく私は何かを誤解していたので、この素晴らしいプロジェクトの著者からのビジネス上の批判を喜んでいます。