Riak docs の Configuring 2i を意訳してみた

# Configuring Secondary Indexes

大雑把な意訳、理解が苦しい箇所は英文と一緒に転載します
http://docs.basho.com/riak/1.3.2/cookbooks/Secondary-Indexes---Configuration/

## Configuration

Riak 1.0 から、2i は ELevelDB バックエンドを使用する設定を行なうことによって有効になります。現在のところ、ELevelDB バックエンドだけが 2i に対応しています。

app.config ファイルの storage_backend 項目に riak_kv_eleveldb_backend を指定してください。2i 使うには、Cluster の全てのノードで 2i が利用できるバックエンドを使用する設定をしなければいけません。

### Using Secondary Indexes with Multi-Backend

2i をサポートしている唯一のローカルストレージバックエンドは ELevelDB です。しかしながら、Riak 1.1.x から 2i を使用しつつ他のバックエンドを使用するマルチバックエンドの設定ができます。

### Migrating an Existing Cluster

Cluster からノードを削除し、2i を有効にした後に、再度 Cluster に追加します。

1. 該当ノードで `riak-admin leave && riak-admin plan && riak-admin commit` を実行します
2. データの再配置が完了した後に `/etc/init.d/riak stop` を実行します
3. ELevelDB バックエンドを使用する設定を行なった後に `/etc/init.d/riak start` を実行します
4. 最後に `riak-admin join && riak-admin plan && riak-admin commit` を実行します

## Indexing an Object

Object にインデックスを付けるために、アプリケーションは 1 つ以上の field/value ペア (インデックス項目と呼ばれる) を Object にタグ付けします。書き込み時に Object はこれらのインデックス項目によってインデックス化されます。アプリケーションは、Object を読み込み、インデックス項目に追加あるいは削除し、Object を書き込むことによって、インデックスを変更できます。Object が削除されると、全てのインデックスから自動的に Object が取り除かれます。

Object の value とそのインデックスは、ひとつの単位として見なされるべきです。Object のインデックスを Object の value から独立して変更する方法はありません。また、その逆もできません。To think of it another way, you can imagine that every time you write an object, it completely de-indexes the object, and then re-indexes the object based on the new set of provided index entries. 

In the case where an object has siblings, the object is indexed under the index entries for ALL of the siblings. When the conflict is resolved, it acts just like an index update. Riak de-indexes the object, and then re-indexes the newly resolved object based on the provided index entries.

インデックス化はアトミック性質があり、Object が書き込まれると同時に更新されます。This means that an object will be present in future index queries as soon as the write operation completes.

### Index Data Types

Riak 1.0 の時点で、Riak は 2 種類のタイプ (Integer と Binnary) のインデックスに対応しました。インデックスにはスキーマが無いため、インデックスフィールド名のサフィックスでインデックスのタイプを区別します。利用できるサフィックスは _int と _bin で、それぞれ Integer と Binary を表します。例えば、timestamp_int は Integer のフィールドで、email_bin は Binary のフィールドを表します。

より複雑なデータタイプ (日付やタイムスタンプのような) は、データを一連の文字としてエンコードし、正確にソートするフォーマットを選ぶことによって、格納することができます。例えば、日付は文字列 "YYYYMMDD" としてエンコードすることができるかもしれません。Float は求められる精密性を決めて、必要に応じて値を掛け、小数点以下を切り捨てることによってエンコードできます。例えば、Float を格納するために、精密さを 1000 に落とし、Float に 1000 を掛け、小数点以下を切り捨てるでしょう。

インデックスフィールド名は、自動的に小文字に変換されます。インデックスフィールドと values は ASCII 文字だけであるべきです。理由としては、それをインデックスとして使用する前に、すべてのユーザーデータをエンコードあるいは標準化することが最も良いからです。2i はマルチバイトの文字で動作するように見えますが、それは避けるべきです。なぜなら、2i の range queries はシングルバイトの文字であると仮定するため、マルチバイトの文字に対しては間違った結果を返すからです。

HTTP インタフェースを使用する場合は、複数の value を持ったインデックスはカンマ区切りで指定します。そのため、アプリケーションでインデックスの value としてカンマを使用することは避けるべきです。

### Index Sizes

Object 上のインデックスは、Object の全体的なサイズを増加させます。従って、Object 上のインデックスの項目数は、Riak Object の推奨される最大サイズ (10MB 程大きくない) によって制限されます。Basho は、1000 個のインデックス項目を付けた Object を負荷試験しました。しかし、ほとんどのアプリケーションはこのような使い方はしないことを期待します。

個々のインデックスサイズはリソースだけに制限されています。しかし、いくつかの HTTP プロキシーは、HTTP ヘッダーのサイズに制限を課していることに注意してください。HTTP インタフェースを使用する場合、インデックスは HTTP ヘッダーとしてエンコードされるため、この影響を受けるかもしれません。

ディスクにおいては、Object の全体的なサイズを増加させます。さらに、インデックスは個別の構造で格納されるため、追加のディスクスペースを消費します。各インデックスを追加することによるオーバヘッドは小さいです。ELevelDB は prefix 圧縮を使用するため、インデックスが必要とするディスクスペースを大きく減らすことができます。

### An Object's Indexes and Value Are Orthogonal

Object のインデックスと Object の value は完全に直交です。インデックスは Object の value に既に存在している情報を射影するかもしれないし、そうでないかもしれません。

意図した使用方法は、アプリケーションが Riak Object の value に JSON のような情報を格納し、後でより容易に検索するために Object にインデックスを付けるであろうということです。インデックスは、JSON に存在しているデータを繰り返すかもしれないし、そうでないかもしれません。例えば、Object はインデックスフィールド "email_bin" を持つと同時に、JSON に email フィールドが存在しているかもしれません。

これはデータが重複する場合に非効率的に見えるかもしれません。しかし、それはいくつかの面白いシナリオに結びつきます。例えば、アプリケーションが Riak に画像を格納し、所有者・ファイルサイズ・作成日などによって画像のインデックスを付けることができます。

## Index Lookups

Riak 1.0 の時点で、インデックスクエリーは、同時にひとつのインデックス項目の制約付きでサポートされました。クエリーは正確な一致あるいは values の範囲のどちらかを指定できます。Range クエリーは最初と最後の value が同じになるかもしれません。クエリーオペレーションは、一致する keys のリストを返します。アプリケーションは各 key で Riak から value を取得するかもしれません。

現在のところ、結果は順序付けられていません。また、2i を使用してオブジェクトのリストを直接 pull back する方法はありません。これは今後かわるかもしれません。

### Lookup Perfomance

2i はドキュメントに基づいたパーティションを使用します。それは、Object のためのインデックスは、Object 自体と同じパーティションに格納されることを意味します。これはクエリー時間のパフォーマンスと密接な関係があります。クエリーを実行すると、システムはクエリーをカバーする複数のパーティションからデータを読み込まなければなりません。システムは、格納されたデータのレプリカがどれだけあるかを確認します。そして、あらゆる落ちているノードも考慮にいれ、結果のフルセットを検索するために調査しなければならない最小のパーティション数を決めます。

デフォルトでは、Riak は全ての Object の 3 個のレプリカを格納するよう構成されます。したがって、システムは正しいパーティションセットを選ぶ限り、システムのパーティションの 1/3 から読むことで、結果を生成することができます。クエリーは、選択されたパーティションにブロードキャストされます。インデックスデータを読み、keys のリストを生成し、要求するノードに結果を送ります。

### Special Fields

インデックスフィールド $key は、2i が有効な場合に、全ての Object 上で暗黙にインデックスされる特別なフィールドです。このフィールドの value は Object の key です。したがって、このフィールドは、アプリケーションが bucket 中の key にまたがって Range クエリーを実行することを可能にします。

インデックスフィールド $bucket は、2i が有効な場合に、全ての Object 上で暗黙にインデックスされるもうひとつの特別なフィールドです。このフィールドの value は Object の bucket です。したがって、このフィールドは、アプリケーションが 2i に基づいた bucket 内の全ての Object を検索することを可能にします。

## End

ちょっと、Indexing an Object セクションの兄弟うんぬんが上手く訳せなかった、というか正しく理解できなかった。あとで読み直してみようと思う。いろいろ試しながら理解していくしかないか。