概要
データの構成や使い勝手の理解を深める為、以前構築したAerospikeの環境(Aerospike環境構築メモ on GCP)を使ってCLIベースでいじってみたのでそのメモ。
Aerospikeのデータ構成
区分 | 定義 |
---|---|
Cluster | Aerospikeのクラスター |
Node | クラスターの構成要素 |
Namespace | 独立したストレージ領域。複数定義可能だがNamespaceを跨いだ参照はできない。RBDでいうところのdatabase やscheme に近い。 |
Set | Recordをグルーピングした領域。RDBのTable に近い。 |
Record | データを出し入れする単位。ValueはJSON形式。RDBのRaw に近い。 |
Bin | データの最小単位。Recordを構成するパーツ。Jsonの要素に当たる。 |
namespace
- 公式ドキュメント
- namespaceはConfigファイル(
/etc/aerospike/aerospike.conf
)を編集して再起動すれば追加や変更ができる - 設定可能な項目はConfiguration Referenceを参照
- 設定の反映にはNodeの再起動が必要
- 全てのNodeに設定を反映しないとクラスター間の整合が取れなくなる
- 全Nodeに一括反映みたいのはなさそう
- よって、そんなに頻繁に作ったり消したりするものではなさそう
データを操作する(AQL版)
Aerospike Query Language(AQL)というSQLライクにデータを操作できるコマンドラインツールが用意されているのでそれを使ってデータを操作してみる。
AQLのプロンプトを開く
$ aql
デフォルトのAerospikeサーバ内にいるならこれでOK。
外部からアクセスする場合はマニュアルに則って-h
や-p
などのオプションを指定する。
データの挿入
INSERT INTO <ns>[.<set>] (PK, <bins>) VALUES (<key>, <values>)
- SQLの構文とほぼ同じだけど、スキーマレスなので
(PK, <bins>)
部分の省略ができないのと、(たぶん)1コマンドで1レコードしか入らない。
例:
aql> insert into test.person (PK, name, age, gender, phone_number) values (1, 'Taro', 20, 'M', 09011112222)
OK, 1 record affected.
データの参照
SELECT * FROM <ns>[.<set>]
例:
aql> select * from test.person
+----------+-----+--------+--------------+
| name | age | gender | phone_number |
+----------+-----+--------+--------------+
| "Hanako" | 22 | "F" | 9011113333 |
| "Taro" | 20 | "M" | 9011112223 |
+----------+-----+--------+--------------+
2 rows in set (0.022 secs)
namespaceまたはsetのデータを参照する。
aql> select name, age from test.person
+----------+-----+
| name | age |
+----------+-----+
| "Hanako" | 22 |
| "Taro" | 20 |
+----------+-----+
2 rows in set (0.022 secs)
取得項目をBinで絞ることも可能
aql> select * from test.person where PK = 1
+--------+-----+--------+--------------+
| name | age | gender | phone_number |
+--------+-----+--------+--------------+
| "Taro" | 20 | "M" | 9011112223 |
+--------+-----+--------+--------------+
1 row in set (0.001 secs)
WHERE句はデフォルトではPK(Record-Key)の等価比較でのみ可能
Bin単位で絞るにはインデックスを貼らないといけない(後述)
[note]
AQLでは現状Record-Keyを参照できないらしい
更新や削除にはKeyが必要なことを考えるとAQLでデータ操作するには限界がある
データの更新
- UPDAET構文はない。
- 同じKey名でINSERTすれば上書かれるので更新になる。
- ただし、更新範囲はRecord単位ではなくBin単位で実行される為、更新しなかったBinはそのまま残る。
例:
aql> select * from test.person where pk = 1
+--------+-----+--------+--------------+
| name | age | gender | phone_number |
+--------+-----+--------+--------------+
| "Taro" | 20 | "M" | 9011112222 |
+--------+-----+--------+--------------+
1 row in set (0.001 secs)
aql> insert into test.person (PK, age) values (1, 21)OK, 1 record affected.
aql> select * from test.person where pk = 1
+--------+-----+--------+--------------+
| name | age | gender | phone_number |
+--------+-----+--------+--------------+
| "Taro" | 21 | "M" | 9011112222 |
+--------+-----+--------+--------------+
1 row in set (0.000 secs)
データの削除
DELETE FROM <ns>[.<set>] WHERE PK=<key>
削除にはPK(Record-key)が必要
例:
aql> delete from test.person where PK = 1
OK, 1 record affected.
インデックスを貼る
CREATE INDEX <index> ON <ns>[.<set>] (<bin>) <type>
- インデックス名はnamespaceでユニークでないければならない
- typeは
NUMERIC
orSTRING
例:
aql> create index idx_person_age_numeric on test.person (age) numeric
OK, 1 index added.
インデックスを貼るとインデックスが貼られたBinでwhere句を使える。
例:
aql> select * from test.person where age = 18
+--------+-----+--------+--------------+
| name | age | gender | phone_number |
+--------+-----+--------+--------------+
| "Jiro" | 18 | "M" | 9022223333 |
+--------+-----+--------+--------------+
1 row in set (0.002 secs)
aql> select * from test.person where age between 18 and 20
+--------+-----+--------+--------------+
| name | age | gender | phone_number |
+--------+-----+--------+--------------+
| "Jiro" | 18 | "M" | 9022223333 |
| "Taro" | 20 | "M" | 9011112222 |
+--------+-----+--------+--------------+
2 rows in set (0.002 secs)
データを操作する(ascli版)
単純にKey指定でデータの出し入れや参照をするだけならAerospike CLI
を使っても可能。
データ操作系
put
recordの挿入
ascli put <ns> <set> <record-key> <record-value>
- record-valueはJSON形式。
- 成否は終了コードが0かどうか
- namespace/set/record-keyが全て同一のデータがある場合は上書かれる
例:
$ ascli put test settest keytest '{"name":"hoge", "age":30, "array":[1,2,3], "map":{"mapkey":"mapvalue"}}'
$ echo $?
0
get
record-valueの取得
ascli get <ns> <set> <record-key>
例:
$ ascli get test settest keytest
{"map": { "mapkey": "mapvalue" }, "array": [ 1, 2, 3 ], "name": "hoge", "age": 30}
exists
record-keyの存在確認
ascli exists <ns> <set> <record-key>
- 存在の有無は終了コードが0かどうか
例:
$ ascli exists test settest keytest
Key keytest exists.
$ echo $?
0
$ ascli exists test settest keytest2
Key keytest2 does not exist.
$ echo $?
2
remove
recordの削除
ascli remove <ns> <set> <record-key>
- 成否は終了コードが0かどうか
例:
$ ascli remove test settest keytest
$ echo $?
0
$ ascli remove test settest keytest
ERROR 2 AEROSPIKE_ERR_RECORD_NOT_FOUND
$ echo $?
2
Scripting
eval
一連のascliのコマンドを実行できるシンプルなスクリプティング環境を呼び出す。
ascli eval
- 標準入力からのコマンドを読み込むので適当なFileに書いたコマンドをパイピングして実行もできる
- eval独自のコマンドもある
- コマンドはスタックに保持される
- スタックは1コマンド1000文字までで、1000コマンドまで保持する。
[Note]
evalはシングルスレッドで動作し、全ての呼び出しをブロックすることに注意する
evalの独自コマンドは以下。
コマンド | 説明 |
---|---|
最後のコマンドからの統計情報を表示する | |
:reset | 蓄積された統計情報をリセットする |
:repeat n | スタック上の全てのコマンドをn回繰り返す |
:clear | スタックを空にする |
:quit | evalから抜ける |
例:
$ ascli eval
put test evaltest test1 '{"name":"hoge"}'
:print
>>
time: 0.94500 ms
success: 1
failure: 0
:reset
:print
>>
time: 0.00000 ms
success: 0
failure: 0
:clear
get test evaltest test1
{"name": "hoge"}
:reset
:repeat 10
{"name": "hoge"}
{"name": "hoge"}
{"name": "hoge"}
{"name": "hoge"}
{"name": "hoge"}
{"name": "hoge"}
{"name": "hoge"}
{"name": "hoge"}
{"name": "hoge"}
{"name": "hoge"}
:print
>>
time: 4.98200 ms
success: 10
failure: 0
:quit
ファイルから実行する場合は以下のような感じでOK。
$ cat {evalfile} | ascli eval
所感
単純なデータ操作ならいいけど、ちょっと複雑なことやろうとすると手詰まりそうな感じ。AerospikeはUDFが定義できるみたいなので複雑な処理はそっちでやれってところかな、と思いました。
とりあえず今回の目的はデータ構成の理解なので一旦こんなもんで。
次はClientを使ってごにょごにょやる予定。