---
title: Cassandra0.7.0のSecondary indexesを試す
tags: []
categories: ["Middleware", "NoSQL", "Cassandra"]
date: 2010-12-22T17:22:23Z
updated: 2011-01-11T15:35:44Z
---

動作確認バージョンはサーバ/クライアントともに`0.7.0`。**(2010/01/12更新)**

[Raptano][1]の記事の写経ですが。

普通のインデックスはカラムのRowキーに対するもので、全てのカラムが持つ。セカンダリインデックスは、カラムの値に対して作られるもの。値での検索がしやすくなる（これまでは転置インデックスのようなものが必要だった）。

### セカンダリインデックス作成

カラムファミリを作成する際にメタデータとしてカラム名を設定でき、その時に`Index Type`も指定できる模様。メタデータに設定する値は以下。

<table>
<tr><th>キー</th><th>設定値</th></tr>
<tr><td><code>column_name</code></td><td>カラム名</td></tr>
<tr><td><code>validation_type</code></td><td>カラム値の型（制限する場合）</td></tr>
<tr><td><code>index_type</code></td><td>インデックスの種類</td></tr>
</table>
（他にあれば後で追加する）


この例では、`full_name`カラムにはインデックスを作らず、`birth_date`カラムにはインデックスを作成している。


    [default@unknown] create keyspace demo;
    62c689d4-0df2-11e0-b3ea-e700f669bcfc
    [default@unknown] use demo;
    Authenticated to keyspace: demo
    [default@demo] create column family users with comparator=UTF8Type and column_metadata=[{column_name:full_name, validation_class:UTF8Type},{column_name:birth_date, validation_class:LongType, index_type:KEYS}];
    b21a9d05-0df2-11e0-b3ea-e700f669bcfc
    [default@demo] describe keyspace demo;
    Keyspace: demo:
      Replication Strategy: org.apache.cassandra.locator.SimpleStrategy
        Replication Factor: 1
      Column Families:
        ColumnFamily: users
          Columns sorted by: org.apache.cassandra.db.marshal.UTF8Type
          Row cache size / save period: 0.0/0
          Key cache size / save period: 200000.0/3600
          Memtable thresholds: 0.2953125/63/60
          GC grace seconds: 864000
          Compaction min/max thresholds: 4/32
          Read repair chance: 1.0
          Column Metadata:
            Column Name: full_name (full_name)
              Validation Class: org.apache.cassandra.db.marshal.UTF8Type
            Column Name: birth_date (birth_date)
              Validation Class: org.apache.cassandra.db.marshal.LongType
              Index Type: KEYS

インデックスの種類は0.7.0の段階では`KEYS`しかサポートされていない。ハッシュのキーみたいなものらしい。
[`bitmap`インデックスが0.7.1からサポートされるとのこと][2]。


何やらそれらしきログが出力されている。

     INFO [Create index users.62697274685f64617465] 2010-12-22 23:11:24,344 ColumnFamilyStore.java (line 325) Creating index org.apache.cassandra.db.Table@6239da8a.users.62697274685f64617465
     INFO [CompactionExecutor:1] 2010-12-22 23:11:24,383 CompactionManager.java (line 341) Compacted to C:\var\lib\cassandra\data\system\Schema-tmp-e-5-Data.db.  15,751 to 11,562 (~73% of original) bytes for 4 keys.  Time: 48ms.
     INFO [Create index users.62697274685f64617465] 2010-12-22 23:11:24,384 ColumnFamilyStore.java (line 339) Index users.62697274685f64617465 complete
     INFO [Create index users.62697274685f64617465] 2010-12-22 23:11:24,385 ColumnFamilyStore.java (line 639) switching in a fresh Memtable for IndexInfo at CommitLogContext(file='/var/lib/cassandra/commitlog\CommitLog-1293039030618.log', position=24885)
     INFO [Create index users.62697274685f64617465] 2010-12-22 23:11:24,386 ColumnFamilyStore.java (line 943) Enqueuing flush of Memtable-IndexInfo@1162212835(41 bytes, 1 operations)
     INFO [FlushWriter:1] 2010-12-22 23:11:24,387 Memtable.java (line 155) Writing Memtable-IndexInfo@1162212835(41 bytes, 1 operations)
     INFO [FlushWriter:1] 2010-12-22 23:11:24,423 Memtable.java (line 162) Completed flushing \var\lib\cassandra\data\system\IndexInfo-e-1-Data.db (164 bytes)

### where句をつけてクエリ実行

セカンダリインデックスを付けたカラムに対してはSQLのような`where`句をつけて値を検索できる。
入っているデータは以下

    [default@demo] list users;
    Using default limit of 100
    -------------------
    RowKey: nobunaga
    => (column=birth_date, value=1534, timestamp=1293042940549000)
    => (column=blood, value=A, timestamp=1293042957506000)
    => (column=full_name, value=Nobunaga Oda, timestamp=1293042893235000)
    -------------------
    RowKey: making
    => (column=birth_date, value=1984, timestamp=1293042776114000)
    => (column=blood, value=B, timestamp=1293042734033000)
    => (column=full_name, value=Toshiaki Maki, timestamp=1293042756442000)
    -------------------
    RowKey: hideyoshi
    => (column=birth_date, value=1537, timestamp=1293042846014000)
    => (column=blood, value=A, timestamp=1293042867208000)
    => (column=full_name, value=Hideyoshi Toyotomi, timestamp=1293042812951000)

検索するのにRowキーではなく、`where`句が使える。

    [default@demo] get users where birth_date = 1984;
    -------------------
    RowKey: making
    => (column=birth_date, value=1984, timestamp=1293042776114000)
    => (column=blood, value=B, timestamp=1293042734033000)
    => (column=full_name, value=Toshiaki Maki, timestamp=1293042756442000)
    
    1 Row Returned.

単体での範囲検索まだサポートされていない模様。多分`KEYS`インデックスではサポートされない。

    [default@demo] get users where birth_date > 1500;
    No indexed columns present in index clause with operator EQ

### 動的にセカンダリインデックス追加

`blood`にはインデックスが作られていないので、

    [default@demo] get users where blood = 'A';
    No indexed columns present in index clause with operator EQ

怒られる。

後からインデックスを追加したい場合は`update`文でスキーマ更新。

    [default@demo] update column family users with comparator=UTF8Type and column_metadata=[{column_name:full_name, validation_class:UTF8Type},{column_name:birth_date, validation_class:LongType, index_type:KEYS},{column_name:blood, validation_class:UTF8Type, index_type:KEYS}];
    9225fc2b-0dfb-11e0-b3ea-e700f669bcfc

ちゃんと更新された。

    [default@demo] describe keyspace demo;
    Keyspace: demo:
      Replication Strategy: org.apache.cassandra.locator.SimpleStrategy
        Replication Factor: 1
      Column Families:
        ColumnFamily: users
          Columns sorted by: org.apache.cassandra.db.marshal.UTF8Type
          Row cache size / save period: 0.0/0
          Key cache size / save period: 200000.0/3600
          Memtable thresholds: 0.2953125/63/60
          GC grace seconds: 864000
          Compaction min/max thresholds: 4/32
          Read repair chance: 1.0
          Column Metadata:
            Column Name: full_name (full_name)
              Validation Class: org.apache.cassandra.db.marshal.UTF8Type
            Column Name: blood (blood)
              Validation Class: org.apache.cassandra.db.marshal.UTF8Type
              Index Type: KEYS
            Column Name: birth_date (birth_date)
              Validation Class: org.apache.cassandra.db.marshal.LongType
              Index Type: KEYS

これで`blood`でも検索できる。

    [default@demo] get users where blood = 'A';
    -------------------
    RowKey: nobunaga
    => (column=birth_date, value=1534, timestamp=1293042940549000)
    => (column=blood, value=A, timestamp=1293042957506000)
    => (column=full_name, value=Nobunaga Oda, timestamp=1293042893235000)
    -------------------
    RowKey: hideyoshi
    => (column=birth_date, value=1537, timestamp=1293042846014000)
    => (column=blood, value=A, timestamp=1293042867208000)
    => (column=full_name, value=Hideyoshi Toyotomi, timestamp=1293042812951000)

    2 Rows Returned.

あるカラムに対して`=`検索が入っていれば他のカラムの範囲検索が使える。

    [default@demo] get users where birth_date > 1535 and blood = 'A';
    -------------------
    RowKey: hideyoshi
    => (column=birth_date, value=1537, timestamp=1293042846014000)
    => (column=blood, value=A, timestamp=1293042867208000)
    => (column=full_name, value=Hideyoshi Toyotomi, timestamp=1293042812951000)

    1 Row Returned.

ただし、`KEYS`インデックスはハッシュのキーみたいなものであり、`btree`ではないため、パフォーマンスは多分良くない。


<div class="amazlet-box" style="margin-bottom:0px;"><div class="amazlet-image" style="float:left;margin:0px 12px 1px 0px;"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/1449390412/ikam-22/ref=nosim/" name="amazletlink" target="_blank"><img src="http://ecx.images-amazon.com/images/I/41eD0bH4XiL._SL160_.jpg" alt="Cassandra: The Definitive Guide" style="border: none;" /></a></div><div class="amazlet-info" style="line-height:120%; margin-bottom: 10px"><div class="amazlet-name" style="margin-bottom:10px;line-height:120%"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/1449390412/ikam-22/ref=nosim/" name="amazletlink" target="_blank">Cassandra: The Definitive Guide</a><div class="amazlet-powered-date" style="font-size:80%;margin-top:5px;line-height:120%">posted with <a href="http://www.amazlet.com/browse/ASIN/1449390412/ikam-22/ref=nosim/" title="Cassandra: The Definitive Guide" target="_blank">amazlet</a> at 10.12.23</div></div><div class="amazlet-detail">Eben Hewitt <br />Oreilly & Associates Inc <br />売り上げランキング: 20382<br /></div><div class="amazlet-sub-info" style="float: left;"><div class="amazlet-link" style="margin-top: 5px"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/1449390412/ikam-22/ref=nosim/" name="amazletlink" target="_blank">Amazon.co.jp で詳細を見る</a></div></div></div><div class="amazlet-footer" style="clear: left"></div></div>


  [1]: http://www.riptano.com/blog/whats-new-cassandra-07-secondary-indexes[default@demo]9393
  [2]: https://issues.apache.org/jira/browse/CASSANDRA-1472
