前回からずいぶん時間がたってしまいました。申し訳ありません。
前回はgetメソッド、そしてget_sliceメソッドでデータを検索する方法を見ていきました。今回は残りのget_range_slices、multiget_slice、get_countの3つのメソッドを見ていきます。
前回同様、検索メソッドの確認の前準備としてデータを投入しておく必要があります。詳細は第7回をご覧ください。
複数のロウを取得する ~get_range_slicesメソッド
前回は基本的に1つのロウに対する操作でしたが、今回は複数のロウを取得してみましょう。そのために使うのがget_range_slicesメソッドです。
まずはコードを見てください。リスト1は郵便番号、住所とその読みを検索するコードです。
SlicePredicateについては前回ご紹介しているので、そちらをご覧ください。
このコードで新たに登場しているのは、KeyRangeとKeySliceという2つのクラスです。
KeyRange
KeyRangeは複数ロウを取得するときのレンジを表すクラスです。これには以下のようなことを設定でき、これに従って検索結果が返されます。
- キーの開始から終了のレンジ
- 取得する最大数
- トークンによるレンジ
リスト1のコードでは、以下のようにキーのレンジを何も指定しないようにしています。
ちなみに、デフォルトでは100件分のデータしか取得しません。そのため、たとえば1000件分取得する場合には、以下のようにする必要があります。
また、キーの開始位置と終了位置を指定する場合は以下のようになります。
このようにキーのレンジを指定できるのですが、いくつか注意点があります(詳細は後述します)。まずは「KeyRangeでキーの取得範囲を指定できる」ことだけわかれば現段階では問題ありません。
KeySlice
次はKeySliceです。KeySliceはget_range_slicesで返される値で、取得したキーと指定されたカラムの集合を持っています。get_range_slicesでは、このKeySliceのListを返します。
取得するコードは、以下のようにKeySliceのListから1つずつ中身を表示するようになっています。
get_range_slicesメソッドで注意すべきところ
ここまでの感じだとCassandraでもレンジクエリが簡単にできている感じがありますが、注意すべきところがあります。それはレンジクエリの順序の問題です。
Cassandraはデータをノード間に分散させる方式として、デフォルトではRandomPartitionerを使います。これは「パーティショナクラス」と呼ばれるもので、キーのハッシュ値を使って、値をノードにランダムに分散させます。
これを使う最大のメリットは、データが均等に分散しやすいため、各ノード間にかかる負担が均等になり、全体として効率がよいことです。ただしその一方で、「レンジクエリの順序が保障されない」というデメリットがあります。つまり、データの挿入順序が保障されず、結果がばらばらに返ってきてしまうのです。
以下はリスト1を実行した結果です。一目瞭然ですね。キーによる順序が一貫せずに値が返ってきています。
パーティショナクラスを使い分ける
では、他に方法がないのでしょうか?
実はCassandraは別の手段を準備してあります。それはOrderPreservingPartitionerというパーティショナを使う方法です。この方法ならば、レンジクエリも想定どおり正しく動いてくれます。
ただしメリットの裏にはデメリットもあるものです。OrderPreservingPartitionerを使うと、データの投入順序を保障するために、Cassandraはデータを均等に分散させるのではなく、決まった順序でデータをノードに投入していきます。
そのため、「あるノードにはデータが大量に存在し、あるノードにはあまりデータがないためにクエリの検索スピードや運用によるノードのリバランスなど考慮しなくてはいけない点が増える可能性があります。
実行すると、皆さんの予想どおり、順序が保障されて表示されます。
RandomPartitionerとOrderPreservingPartitionerのどちらを使うかは、Cassandraを使う場合に非常に難しい問題で、一概には答えられません。しかし、まずは両者の違いを把握しておくことが大事です。
また、パーティショナはCassandraではグローバルな設定でデータ構造にも影響を与えるので、storage-conf.xml全体で1つの設定になっています。どちらを使うか、注意深く考えて設計する必要があります。
特定のキーの行を複数取得する ~multiget_sliceメソッド
ある特定キーの集合を取得したいときに使うのがmultiget_sliceメソッドです。まずはコードを見てみましょう。
リスト2の例は
キーが1080074、1080075のロウを検索
その中の郵便番号と住所のカラムを取得
という処理を行うものです。「get_sliceを複数キーに対応させたAPI」だと思っていただければ間違いありません。
カラム数を取得するには ~get_countメソッド
カラム数を取得するには、get_countメソッドを使います。シンプルに「キーに対するロウ内にどれだけのカラムがあるか」を返します。以下はコードの抜粋です。
今回は、簡単ですが、get_range_slices、multiget_slice、get_countの3つのメソッドの使い方を見ていきました。
この中でやはり重要なのが、レンジクエリを実現するget_range_slicesです。レンジクエリを多用するシステムではCassandraのパーティショナを変更する必要があるでしょう。ただしその場合、運用保守で定期的にノードを再バランシングする必要が出てくるかもしれません。
今回までは、ThriftによるCassandraのネイティブなAPIを見ていきました。次回からThrift APIを隠蔽してくれるフレームワークやライブラリを見ていきます。