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


# Secondary Indexes

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

## Introduction

Riak の Secondary Indexing (以後 2i) は、開発者が Riak に格納されている Object にひとつ以上の検索できる value をタグ付けすることを可能にします。

KV データは 2i に完全に曖昧であるので、ユーザーは 2i にインデックスの属性が何かとそのインデックスの value が何であるべきかを厳密に伝えなければいけません。これは Riak Search と異なり、データをパースしスキーマに基づいたインデックスを構築します。Riak の 2i は、LevelDB バックエンドストレージを必須とします。

## Features

インデックスの属性は 2 種類 (Interges と Binary) を許可します。ひとつのインデックスで範囲検索またはユニーク検索を行なうクエリーを可能にします。クエリーの結果は、MapReduce の入力として使用できます。

## When to Use Secondary Indexes

Object の bucket/key ペア以外の条件でデータを検索したい場合に 2i は有効です。インデックスは、Riak の Object に metadata を追加することによって作成されます。

binary ファイルのように曖昧な BLOG な value を格納している場合に 2i は有効です。インデックスを使用して追加の属性を付けることができます。

簡易的に使える検索機能を望む場合に 2i は有効です。2i は、Riak Search のような検索に使うスキーマを必須とせず、基礎的なクエリーインターフェースを備えています。

Anti Entropy (存在するデータのレプリカを全て比較し、全てのレプリカを最新のバージョンの置き換えること) を望む場合に 2i は有効です。2i は Object 上の metadata で、インデックスは同じノードに属します。2i piggybacks off of read-repair.

## When Not to Use Secondary Indexes

Ring サイズが 512 パーティションを超える場合に 2i は適しません。2i は大規模な Cluster においてパフォーマンス問題の原因になります。

2i のサポートしている範囲検索またはユニーク検索を超える用途の場合に 2i は適しません。

各種の要素からなるクエリーを使いたい場合に 2i は適しません。例えば "last_name=zezeski AND state=MD" のようなクエリーは、2 つのクエリーに分割し、結果をマージする必要があるでしょう。

ページ付けが必要な場合に、2i は適しません。2i はページ付けをサポートしません。常に全ての結果が返されます。これは MapReduce を使用することである程度実現できますが、複雑になります。

全範囲を順序付けた結果が必要な場合に 2i は適しません。2i の結果は、部分的に順序付けします。全範囲を順序付けるには、クライアントまたは MapReduce で扱わなければいけません。

## How It Works

 2i はドキュメントベースのパーティションを使用します。ローカルインデックスとして知られているように、インデックスは各ドキュメントの中に属します。2i は HTTP ヘッダーに似ている key/value のリストです。書き込み時に、Object は key/value の metadata で構成されるインデックス項目でタグ付けされます。この metadata は一致する keys を検索できます。 

![Secondary-index-example.png](http://docs.basho.com/shared/1.3.2/images/Secondary-index-example.png?1371843153)

インデックスは複数のサーバにまたがって存在します。そのため、複数の仮想ノードでクエリーを実行し、結果をマージしなければなりません。Object のためのインデックスは Object と同じパーティションに格納されるため、パフォーマンス問題が生じるかもしれません。クエリーを実行すると、システムは、クエリーをカバーするパーティションから読み込みます。システムは、格納されたデータのレプリカがどれだけあるかを確認します。そして、あらゆる落ちているノードも考慮にいれ、結果のフルセットを検索するために調査しなければならない最小のパーティション数を決めます。

アプリケーションは、Object を読み込み、インデックス項目に追加あるいは削除し、Object を書き込むことによって、インデックスを変更できます。Object が削除されると、全てのインデックスから自動的に Object が取り除かれます。Object の value とそのインデックスは、ひとつの単位として見なされるべきです。Object のインデックスを Object の value から独立して変更する方法はありません。またその逆もできません。インデックスはアトミックで、Object を書き込むと同時に更新されます。This means that an object will be present in future index queries as soon as the write operation completes.

## Query Interfaces and Examples

この例では、ユーザーデータを格納する bucket/key のペアを "users/john_smith" とします。ユーザーデータの、twitter name 属性と email address 属性に 2i を設定します。

### Inserting the object with Secondary Indexes:

Object は users/john_smith に格納されます。Object は "jsmith123" の value を持った "twitter_bin" と呼ばれる 2i があります。Object は "jsmith@basho.com" の value を持った "email_bin" と呼ばれる 2i があります。

```
curl -X POST \
-H 'x-riak-index-twitter_bin: jsmith123' \
-H 'x-riak-index-email_bin: jsmith@basho.com' \
-d '...user data...' \ 
http://localhost:8098/buckets/users/keys/john_smith
```
### Querying the object with Secondary Indexes:

twitter name で検索するクエリーを下記に示します。

```
curl localhost:8098/buckets/users/index/twitter_bin/jsmith123
```

それに対するレスポンスを下記に示します。

```
{"keys":["john_smith"]}
```

## End

いまいち理解できない部分があったけど、雰囲気はつかめた。Riak はあらかじめパーティション数を決めるのもスケールアウトしにくいけど、2i を使うとさらにスケールアウトしにくい制約があるんだな。本番投入してるサービスは、どうしてるんだろ。