[groonga-dev,01974] Re: Mroongaで複合主キーを使ったテーブルにおける検索について

Back to archive index

Kouhei Sutou kou****@clear*****
2013年 12月 9日 (月) 12:39:51 JST


須藤です。

In <CANM+HhcE8htVB0qW8Du3+W2aM8vEii-Gzy_517zh****@mail*****>
  "[groonga-dev,01970] Re: Mroongaで複合主キーを使ったテーブルにおける検索について" on Mon, 9 Dec 2013 08:33:16 +0900,
  Naoya Murakami <visio****@gmail*****> wrote:

>> <質問>
>> Mroongaで複数のカラムで主キーを作った場合は、主キーのカラムは、
>> インデックスを使って検索できないのでしょうか?

Mroongaだと普通にできて、Groongaだと頑張ればできる、が答えに
なります。

>> CREATE TABLE IF NOT EXISTS `text_multi` (
>>   `id` varchar(20) NOT NULL,
>>   `lang` varchar(2) NOT NULL,
>>   `year` int(10) NOT NULL,
>>   `text` text NOT NULL,
>>   PRIMARY KEY (`id`,`lang`,`year`),
>>   FULLTEXT INDEX `text` (`text`)
>> ) ENGINE=mroonga DEFAULT CHARSET=utf8;

この場合、(Mroongaではなく)Groongaから見ると、_keyは以下の
ようなフォーマットの値が入っています。

  "${正規化後のidの値(20バイト)}${正規化後のlangの値(2バイト)}${yearの値(4バイト)}"

idが20バイト以下の場合とlangが2バイト以下の場合は右側が
\0(1バイト中すべてのビットが0の値)で埋められます。

yearの値のところはちょっと加工してあって、正の値なら一番左の
ビットがたって、負の値なら落ちるようになっています。

>> INSERT INTO text_multi VALUES ("200","ja",2009,"今日は雨だ。");

なら

  200\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ja\x80\0\x0a\xD9

となります。

なので、

>> _keyには、idのカラムのみの値が入っているように見えますが、idのみで
>> 検索してもあまりパフォーマンスが良くありません。

となっているわけではないのです。

>> 別途、KEY `id` (`id`)を作ればはやく検索できそうですが、
>> そのようにする必要がありますか?

そうしてもインデックスを使って検索できます。

他の少し面倒な方法だと、

  select text_multi --query '_key:^200'

というように前方一致検索をします。

本当は「_key:^200」の後に\0を入れないといけないのですが、こ
こでは\0を書けないので、もし、別に「200X」というキーがあった
らそっちもヒットしてしまいます。

あと、注意する点として、「正規化後の値」を指定する必要がある
ということです。NormalizerMySQLUnicodeCIなどは大文字に正規化
するため、idが「xxx」の場合でも「_key:^XXX」と検索しなければ
いけません。


まぁ、別途インデックスを作った方が楽ですね!

-- 
須藤 功平 <kou****@clear*****>
株式会社クリアコード <http://www.clear-code.com/> (03-6231-7270)

Groongaサポート:
  http://groonga.org/ja/support/
パッチ採用はじめました:
  http://www.clear-code.com/recruitment/
コミットへのコメントサービスはじめました:
  http://www.clear-code.com/services/commit-comment.html




groonga-dev メーリングリストの案内
Back to archive index