Cassandra 0.7.4でColumnFamilyのキーを取得する。



Cassandraのメーリングリストで「userアットcassandra.apache」というのがあります。
そこの投稿で「newbie question: how do I know the total number of rows of a cf?」という質問があったので、調べてみました。
 
質問の回答は

 1. run a map reduce. Pig is really helpful in these cases. Make sure you run your MR using Hadoop task tracker on your nodes - or your performance will take a hit.
 2. dump all keys using sstablekeys script from relevant files on all machines and count unique values. I do that using "sort -n  keys.txt |uniq >> unique_keys.txt"

とか

 sort -n keys.txt | uniq | wc -l

とあるのだが、keys.txtはどうやって出力するのか調べてみました。
 
Cassandraのbinディレクトリをみると「bin/sstablekeys」というのがある。
ついでに、「/bin/sstable2json」というのもある。

とりあえず、実行してみた。

 Usage: sstablekeys <sstable>

 
というものを指定しないといけないらしい。とはなんだろう?
sstablekeysの中身をみてみると

if [ "x$CASSANDRA_INCLUDE" = "x" ]; then
    for include in /usr/share/cassandra/cassandra.in.sh \
                   /usr/local/share/cassandra/cassandra.in.sh \
                   /opt/cassandra/cassandra.in.sh \
                   ~/.cassandra.in.sh \
                   /usr/local/cassandra/bin/cassandra.in.sh \
                   `dirname $0`/cassandra.in.sh; do
        if [ -r $include ]; then
            . $include
            break
        fi
    done
elif [ -r $CASSANDRA_INCLUDE ]; then
    . $CASSANDRA_INCLUDE
fi

 
cassandra.in.shのありかを指定しないといけないらしいので「/usr/local/cassandra/bin/cassandra.in.sh \」を追加してみました。
「./bin/sstablekeys Keyspace1」を実行してみると、

 Exception in thread "main" java.util.NoSuchElementException
        at java.util.StringTokenizer.nextToken(StringTokenizer.java:332)
        at org.apache.cassandra.io.sstable.Descriptor.fromFilename(Descriptor.java:139)
        at org.apache.cassandra.io.sstable.Descriptor.fromFilename(Descriptor.java:119)
        at org.apache.cassandra.tools.SSTableExport.enumeratekeys(SSTableExport.java:271)
        at org.apache.cassandra.tools.SSTableExport.main(SSTableExport.java:462)

とでてしまいました。
 
org.apache.cassandra.tools.SSTableExportのソース462行目を読んでみる。enumeratekeys(ssTableFileName, System.out);というメソッドがあるみたい。
実装を確認してみます。

    public static void enumeratekeys(String ssTableFile, PrintStream outs)
    throws IOException
    {
        Descriptor desc = Descriptor.fromFilename(ssTableFile);
        KeyIterator iter = new KeyIterator(desc);
        DecoratedKey lastKey = null;
        while (iter.hasNext())
        {
            DecoratedKey key = iter.next();

            // validate order of the keys in the sstable
            if (lastKey != null && lastKey.compareTo(key) > 0 )
                throw new IOException("Key out of order! " + lastKey + " > " + key);
            lastKey = key;

            outs.println(bytesToHex(key.key));
        }
        iter.close();
        outs.flush();
    }

 
標準出力にssTableFileというものをだしているっぽい。多分。
「/var/lib/cassandra/data/Keyspace1/」にStandard2-f-1-Index.dbというファイルがあるので
指定して実行してみました。

 $ ./bin/sstablekeys /var/lib/cassandra/data/Keyspace1/Standard2-f-1-Index.db
   6d69636869626174616a65737369636133
   736173616b696e6f7a6f6d69
   736173616b696e6f7a6f6d6933

なんかそれっぽいのがでました。
「./bin/sstable2json /var/lib/cassandra/data/Keyspace1/Standard2-f-1-Index.db」も試してみました。

 $ ./bin/sstable2json /var/lib/cassandra/data/Keyspace1/Standard2-f-1-Index.db
 {
"6d69636869626174616a65737369636133": [["616765", "3235", 1300717063585, false], ["6669727374", "4a657373696361", 1300717063585, false], ["6c617374", "4d6963686962617461", 1300717063585, false]],
"736173616b696e6f7a6f6d69": [["616765", "3232", 1300716830310000, false], ["6669727374", "6e6f7a6f6d69", 1300716779268000, false], ["6c617374", "736173616b69", 1300716823681000, false]],
"736173616b696e6f7a6f6d6933": [["616765", "3232", 1300717063585, false], ["6669727374", "6e6f7a6f6d69", 1300717063585, false], ["6c617374", "736173616b69", 1300717063585, false]]
}

それっぽいデータがまたでました。
 
「Standard2-f-1-Data.db」「Standard2-f-1-Filter.db」「Standard2-f-1-Statistics.db」でもそれぞれ
同じようにキーが出力されるみたいです。