Couchbaseベンチマークツールn1qlback解説

# はじめに

データベースを運用するに当たって、ベンチマーク(ストレス)テストは避けて通れない要素です。

Couchbase Serverには、それぞれ以下の記事で解説したように、Dataサービスと、Queryサービスという二種類のサービスが、基本的なデータ操作に関係しています。

- [Couchbase Server アーキテクチャ解説: Dataサービス](https://qiita.com/yoshiyuki_kono/items/71077529483149f257e1)
- [Couchbase Server アーキテクチャ解説: Queryサービス](https://qiita.com/yoshiyuki_kono/items/362e29cab6bc7397bab5)

それぞれのサービスは、以下のような特徴を持ち、ベンチマークの目的のためにも、下記のように異なるツールが用意されています。

|サービス|アクセス形態|データ操作|ストレスツール|
|:--|:--------------|:--|:--|
|Dataサービス|キーバリューストアへのアクセス|CREATE, READ, UPDATE, DELETE|pillowfight|
|Queryサービス|SQLをJSON操作に拡張したクエリによるアクセス|（主に）READ|n1qlback|

Queryサービス(N1QLクエリ)は、'INSERT'、'DELETE'や'UPDATE'もサポートしていますが、アプリケーション連携において、キーによる操作が可能なところで、クエリを用いることは、アンチパターンとなるため（WHERE句を用いた条件によるデータ削除・更新や、"INSERT .. FROM SELECT..."のような処理が必要な要件がある場合は、その限りではありません）、実際的には、多くの場合、READの処理が中心となります。

Dataサービスのためのストレスツールであるpillowfightについては、下記の記事をご参考ください。
[Couchbaseベンチマークツールpillowfight解説](https://qiita.com/yoshiyuki_kono/items/f78235ece4a5d07ea434)

# n1qlbackの使い方

n1qlbackは、pillowfight同様、Couchbase C SDK libcouchbaseの一部として提供されます。
（インストール手順については、上記の記事をご参考ください）


n1qlback は、指定された数のスレッドを作成し、それぞれがユーザー定義のクエリのセットを実行します。

n1qlbackでは、実行するクエリを含むファイル（1行に1クエリ）へのパスを渡す必要があります。クエリは、下記のように、サーバーに送信される実際のHTTP POST本文の形式（JSON形式）である必要があります。単純なクエリの場合、ステートメントフィールドのみを設定します。

```JSON
{"statement":"SELECT country FROM `travel-sample`"}
{"statement":"SELECT country, COUNT(country) FROM `travel-sample` GROUP BY country"}
```

次の例は、名前付きパラメータの使用方法を示しています。

```JSON
{"statement":"SELECT RAW meta().id FROM `travel-sample` WHERE type=$type LIMIT 1", "$type":"airline"}
```

処理を実行する前にコマンドにより削除される特別なオプション「n1qlback」が、あります。実行前に特定のクエリを準備する必要があるかどうかを判断できます。

```JSON
{"statement":"SELECT * FROM `travel-sample` WHERE type=$type LIMIT 10", "$type":"airline", "n1qlback": {"prepare": true}}
```

n1qlbackを利用する際には、Couchbase Serverに必要なリソース（データ、インデックス）が定義されている必要があります（当たり前のようですが、ツールが必要になるインデックスを事前に作成するようなような補助機能は備えていないということです）。


# オプション解説

## n1qlbackオプション
- -f --queryfile=_PATH_: JSON形式で実行するクエリ本文を含むファイルへのパス。1行に1つのクエリ。
- -t, --num-threads=_NTHREADS_: 同時に実行するスレッド数（クライアントインスタンスの数）を設定します。各スレッドには、それぞれクライアントオブジェクトが割り当てられます。
- -e, --error-log=PATH: ファイルへのパスを指定します。そのファイルへコマンドは失敗したクエリとエラーの詳細を書き込みます。このオプションの使用により、ERRORSメトリックがゼロでない理由を把握することができます。

## 共通オプション

以下のオプションは、クラスターへの接続に関連する、`libcouchbase`コマンドの共通オプションです。

|省略|非省略|説明|
|:--|:--------------|:--|
|-U|--spec|接続文字列 [デフォルト='couchbase：//localhost/default' ] |
|-u|--username|ユーザー名 [デフォルト= '' ] |
|-P|--password|バケットパスワード [デフォルト= '' ]| 
|-T|--timings|実行終了時にコマンドタイミングをダンプします。これにより、実行されたコマンドの待ち時間を示すヒストグラムが表示されます。(詳細：[cbstats timings](https://docs.couchbase.com/server/current/cli/cbstats/cbstats-timing.html)) [デフォルト= FALSE]|
|-v|--verbose|デバッグ出力を有効にする [デフォルト= FALSE]|
|-D|--cparam|接続のための追加のオプション(`<OPTION>=<VALUE>`の書式で指定)。例えば、KV操作タイムアウトには`-D-timeout=<SECONDS>`を使用する[デフォルト=]|
|-y|--compress|送信データの圧縮をオンにします（ sec-OND時刻力圧縮） [デフォルト= FALSE]|
||--truststorepath|[デフォルト= '' ] |
||--certpath|サーバーSSL証明書へのパス[デフォルト= '' ] |
||--keypath|クライアントSSL秘密鍵へのパス[デフォルト= '' ] |
||--dump|操作完了後に詳細な内部状態をダンプする [Default = FALSE]|

## 追加オプション
次のオプションは、`：couchbase：//host/bucket？option1=value1＆option2=value2`のような、URIスタイルのクエリパラメータ（例）として、接続文字列に含めることができます。 あるいは、個々のキー=値のペアとしてDスイッチと共に利用することができます（-Dは内部で接続文字列を作成し、コマンドラインでオプションを簡単に渡すための便宜のために提供されています）。

- operation_timeout=SECONDS: 操作タイムアウトを秒単位で指定します。これは、タイムアウトするまでに、クライアントが操作の完了を待つ時間です。デフォルトは2.5です。
- config_cache=PATH: クライアントがブートストラップ操作によって接続するのではなく、ファイルベースの構成キャッシュを利用できるようにします。ファイルが存在しない場合、クライアントは最初にクラスターに接続し、次にブートストラップ情報をファイルにキャッシュします。
- certpath=PATH: サーバーのSSL証明書へのパス。これは通常、証明書がシステムのopensslインストールにすでに追加されていない限り、SSL接続に必要です（couchbases：//スキームでのみ適用可能）
- ssl=no_verify: SSLの証明書検証を一時的に無効にします（couchbases：//スキームでのみ適用可能）。これは、SSL機能をすばやくデバッグするためにのみ使用してください。
- sasl_mech_force=MECHANISM: 初期接続を実行するときに、特定のSASLメカニズムを強制的に使用します。これは、デバッグ目的でのみ変更する必要があります。現在サポートされているメカニズムは、PLAINとCRAM-MD5です。


# 実行例
以下は、3つのクエリが5つのスレッドで実行されるファイルを作成します。また、クエリに必要なインデックスの作成を事前に行っています。

```shell-session
cbc n1ql -U couchbase://192.168.72.101/a_bucket 'CREATE INDEX ix_name ON `travel-sample`(name)'
cbc n1ql -U couchbase://192.168.72.101/a_bucket 'CREATE INDEX ix_country ON `travel-sample`(country)'

cat queries.txt <<EOF
{"statement":"SELECT country FROM `travel-sample` WHERE `travel-sample`.country = \"United States\""}
{"statement":"SELECT name FROM `travel-sample` LIMIT 10"}
{"statement":"SELECT country, COUNT(country) FROM `travel-sample` GROUP BY country"}
EOF

cbc-n1qlback -U couchbase://192.168.72.101/a_bucket -t 5 -f queries.txt
```



# 関連情報

[Install and Start Using the C SDK with Couchbase Server](https://docs.couchbase.com/c-sdk/current/hello-world/start-using-sdk.html)


[cbc-n1qlbackドキュメント](https://github.com/couchbase/libcouchbase/blob/master/doc/cbc-n1qlback.markdown)