磯部 和広
k-iso****@rozet*****
2012年 11月 13日 (火) 21:45:20 JST
いつもお世話になっております。 首題の件につき質問させて下さい。 動作環境は、下記です。 [root @ DB09 data]# head -n 1 groonga.log 2012-05-18 18:50:01.795320|n|e897e700|mroonga 2.02 started. [root @ DB09 data]# cat /etc/redhat-release CentOS release 6.2 (Final) [root @ DB09 data]# 現在、プライマリーキーを張った「id」フィールドに、 SQLでselectを行うと 何故か「0」と表示される行が3つある という状況になってしまっています。 mysql> desc RZ_COMPARISON; +----------------------+------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +----------------------+------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | category_id | int(11) | NO | | NULL | | | original_data_id | int(11) | YES | | NULL | | | whole_flag | tinyint(4) | YES | | NULL | | | lang_type | tinyint(4) | YES | | NULL | | | wa_original | mediumtext | NO | MUL | NULL | | | std_original | mediumtext | NO | MUL | NULL | | | wa_trans | mediumtext | NO | MUL | NULL | | | original | mediumtext | NO | MUL | NULL | | | trans | mediumtext | NO | MUL | NULL | | | original_line_length | int(11) | YES | | NULL | | | trans_line_length | int(11) | YES | | NULL | | | reg_date | datetime | YES | | NULL | | | reg_id | int(11) | YES | | NULL | | | upd_date | datetime | YES | | NULL | | | upd_id | int(11) | YES | | NULL | | +----------------------+------------+------+-----+---------+----------------+ 16 rows in set (0.00 sec) mysql> select id from RZ_COMPARISON where original_line_length = 0; +----+ | id | +----+ | 0 | | 0 | | 0 | +----+ 3 rows in set (0.00 sec) mysql> プライマリーキーなので、本来有り得ない状況なのですが・・・ が、where id=0 を指定してselectしても1件もヒットしません。 mysql> select id from RZ_COMPARISON where id = 0; Empty set (0.00 sec) mysql> どうも、nroongaエンジン固有の問題のようです・・・ これだけだと、問題解決の為に何も手掛かりが得られないので 下記の実験を行いました。 mysql> select count(1) from RZ_COMPARISON; +----------+ | count(1) | +----------+ | 2656 | +----------+ 1 row in set (0.00 sec) mysql> select min(id), max(id) from RZ_COMPARISON; +---------+---------+ | min(id) | max(id) | +---------+---------+ | 246619 | 250513 | +---------+---------+ 1 row in set (0.00 sec) mysql> select count(1) from RZ_COMPARISON where id <= 250513; +----------+ | count(1) | +----------+ | 2656 | +----------+ 1 row in set (0.01 sec) mysql> select count(1) from RZ_COMPARISON where id >= 246619; +----------+ | count(1) | +----------+ | 1587 | +----------+ 1 row in set (0.00 sec) mysql> 御覧のように、全件の数値と、 id <= max(id) のものは件数が一致しますが id >= min(id) のものは件数が一致しない という状況です。 繰り返しますが、idはプライマリーキーです。 当然インデックスが張ってあります。 どうも、インデックスの統計情報がおかしくなっているようです。 ※インデックスを指定してのカウントは、統計情報を使用すると推測しています。 インデックスを張ってある項目のminやmax値も、同様に インデックスの統計情報から取得しているのだと思います。 次に、データをファイルに出力してみて状況を見てみました。 [root @ DB09 data]# echo 'select id from RZ_COMPARISON' | mysql rz_00003 > /tmp/a [root @ DB09 data]# wc -l /tmp/a 2657 /tmp/a [root @ DB09 data]# head -n 2 /tmp/a id 246619 [root @ DB09 data]# tail -n 2 /tmp/a 250509 250510 [root @ DB09 data]# あれれ? 変です。 idの最小値と、ファイルに出力されたidの最小値は一致するのですが 最大値が一致しません。 念の為ソートしてみましたが、結果は一緒です。 [root @ DB09 data]# echo 'select id from RZ_COMPARISON order by id' | mysql rz_00003 > /tmp/b [root @ DB09 data]# wc -l /tmp/b 2657 /tmp/b [root @ DB09 data]# head -n 2 /tmp/b id 246619 [root @ DB09 data]# tail -n 2 /tmp/b 250509 250510 [root @ DB09 data]# 更に確認しました。 [root @ DB09 data]# sort -n /tmp/b | head id 883 884 885 886 887 888 889 890 891 [root @ DB09 data]# SQLで取得したIDの最小値より小さいIDが・・・ /tmp/b は、order by idを指定してあったのに、正しくソートされていません。 [root @ DB09 data]# grep -n '^883' /tmp/b 4:883 [root @ DB09 data]# 4行目に出現しているようなので、先頭10件を表示してみます。 [root @ DB09 data]# head -n 10 /tmp/b id 246619 246621 883 884 885 886 887 888 889 [root @ DB09 data]# head -n 10 /tmp/a id 246619 246621 883 884 885 886 887 888 889 [root @ DB09 data]# order by句もインデックスを使用する筈なので、 やはりインデックス絡みのようです。 というわけで、首題の件名となりました。 どうも、 select id from RZ_COMPARISON where original_line_length = 0; にて、ありえない筈のプリマリーキーに同一の「0」として見える値が 3件見える のと IDの最大値と、データ出力した際のIDの最大値の差が3 とが関係しているようです。 それとは別に、min関係のインデックス情報がおかしいようです。 ちなみに、経緯は下記です。 このテーブルのプライマリーキーのid欄には、AUTO_INCREMENT属性が付いていますが それとは別建てで ・IDだけを連番管理するテーブルに新規IDを採番 ・採番したIDを用いて、このテーブルにデータをインサート する仕組みになっています。 その際に 採番用テーブルのID値の最大値と、実際のデータのIDの最大値が違う(3件ず れている) のに、別のエンジニアがたまたま気付きました。 で、自分が相談されて調査した所・・・という流れです。 尚、データは随時、追加や削除を繰り返していますのでidは飛び飛びになります。 最後に、テーブルの定義を載せておきます。 CREATE TABLE `RZ_COMPARISON` ( `id` int(11) NOT NULL AUTO_INCREMENT, `category_id` int(11) NOT NULL, `original_data_id` int(11) DEFAULT NULL, `whole_flag` tinyint(4) DEFAULT NULL, `lang_type` tinyint(4) DEFAULT NULL, `wa_original` mediumtext NOT NULL, `std_original` mediumtext NOT NULL, `wa_trans` mediumtext NOT NULL, `original` mediumtext NOT NULL, `trans` mediumtext NOT NULL, `original_line_length` int(11) DEFAULT NULL, `trans_line_length` int(11) DEFAULT NULL, `reg_date` datetime DEFAULT NULL, `reg_id` int(11) DEFAULT NULL, `upd_date` datetime DEFAULT NULL, `upd_id` int(11) DEFAULT NULL, PRIMARY KEY (`id`), FULLTEXT KEY `index_so` (`std_original`) COMMENT 'parser "TokenDelimit"', FULLTEXT KEY `index_swt` (`wa_trans`) COMMENT 'parser\n"TokenDelimit"', FULLTEXT KEY `index_o` (`original`), FULLTEXT KEY `index_t` (`trans`), FULLTEXT KEY `index_wo` (`wa_original`) COMMENT 'parser\n"TokenDelimit"' ) ENGINE=mroonga DEFAULT CHARSET=utf8;