Aerospike にキーの情報も格納するには

aql コマンドでキーそのものも確認したい

分散型 KVS である Aerospike では、 aql という SQL ライクにデータを確認・操作できるコマンドラインインターフェースが提供されています。使える機能はかなり限られているものの、 KVS にもかかわらずまるで RDB であるかのように扱えるので、データの確認には重宝しています。

たとえば、以下のように INSERT したり SELECT したりできます。

1
2
3
4
5
6
7
8
9
10
aql> INSERT INTO test.testset (PK, a, b) VALUES ('xyz', 'abc', 123)
OK, 1 record affected.

aql> SELECT * FROM test.testset
+-------+-----+
| a | b |
+-------+-----+
| "abc" | 123 |
+-------+-----+
1 row in set (0.058 secs)

しかしながらここで注目してもらいたいのが、キーである 'xyz' が表示されていないということです。

Aerospike は内部的にはキーそのものを使用していない

Aerospike は内部的には、レコードを指定するのにキーそのものではなくそのハッシュ値を使用しています。 Aerospikeのデータモデルの説明 から引用してみます。

Key / Digest

In the application, each record will have a key associated with it. This key is what the application will use to read or write the record.

However, when the key is sent to the database, the key (together with the set information) is hashed into a 160-bit digest. Within the database, the digest is used address the record for all operations.

The key is used primarily in the application, while the digest is primarily used for addressing the record in the database.

The key maybe either an Integer, String, or Bytes value.n

キー / ダイジェスト

アプリケーションの中では、各レコードにはそれに対応するキーがあります。このキーはアプリケーションがレコードを読み出したり書き出したりするのに使うものです。

しかしながら、キーがデータベースに送られるときには、そのキー(とセットの情報)は 160 bit のダイジェストにハッシュ化されます。データベースの中では、すべての操作において、レコードを指定するのにはそのダイジェストが使用されます。

キーは主にアプリケーションの中で使用され、ダイジェストは主にデータベースの中でレコードを指定するのに使用されます。

キーは整数か文字列、バイト値のどれかです。

このような事情のため、 aql ではそのままではキーが表示されないようです。

Aerospike にキーの情報も格納するには

aql でキーも表示するようにするためには、まずそもそも Aerospike にキーそのものの情報も格納するようにしなければなりません。つまり、クライアントアプリケーションからデータを送る際に、キーの情報も保存するように明示的に指定する必要があります。どのクライアントライブラリにも WritePolicy.sendKey のようなフラグがあるはずなので、それを true に設定します。

たとえば、 Go 言語のサンプルアプリケーションの場合には、以下のようにします。

main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package main

import (
"fmt"
"os"

asc "github.com/aerospike/aerospike-client-go"
)

func panicOnErr(err error) {
if err != nil {
panic(err)
}
}

func main() {
cl, err := asc.NewClient("127.0.0.1", 3000)
panicOnErr(err)

key, err := asc.NewKey("test", "testset", "xyz")
panicOnErr(err)

// define some bins with data
bins := asc.BinMap{
"a": "abc",
"b": 123,
}

// write the bins
wp := asc.NewWritePolicy(0, 0)
wp.SendKey = true // ここでキーそのものも送信するように指定する!
err = cl.Put(wp, key, bins)
panicOnErr(err)

rec, err := cl.Get(nil, key)
panicOnErr(err)

fmt.Printf("%#v\n", *rec)
}

このプログラムを実行してから、 aql で確認してみます。

1
2
3
4
5
6
7
8
9
10
11
$ go run main.go
aerospike.Record{Key:(*aerospike.Key)(0xc8200da000), Node:(*aerospike.Node)(0xc8200ae000), Bins:aerospike.BinMap{"a":"abc", "b":123}, Generation:1, Expiration:432000}

$ aql
aql> SELECT * FROM test.testset
+-------+-------+-----+
| key | a | b |
+-------+-------+-----+
| "xyz" | "abc" | 123 |
+-------+-------+-----+
1 row in set (0.055 secs)

きちんとキーも表示されるようになりましたね。