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