2011年8月31日

[mysql 15624] Re: mysql 5.5.9でのsetnames sjisで性能低下

こんにちは、平塚です。

On Tue, 30 Aug 2011 20:29:54 +0900 (LMT)
Etsuo SUMIYA <sumiya-e@xxxxx> wrote:

> "set names sjis"を実行すると、t2の
> rowsが10となり、indexがきかず、全スキャンかかってしまうようです。

いただいたテストケースは
MySQL 5.5.11で再現して、MySQL 5.5.12だと再現しませんでした。
たぶん↓これです。
http://bugs.mysql.com/bug.php?id=60625

ただそれとは別に
最新のMySQL 5.5.15でも再現するケースを作れたので、バグ報告してみました。
http://bugs.mysql.com/bug.php?id=62307

仕組みとしては、tm = '20:01'という検索条件を
CONVERT(tm USING SJIS sjis) = '20:01'
に変換するわりと残念なロジックがMySQL 5.5から入っていて、
これの発動条件の一つがcharacter_set_connection = ucs2あるいはsjis
となっているようです。

ucs2のためにはこのロジックがどうしても必要なようですが、
sjisは巻き添えを喰らった感があります。

このロジックが発動するとファンクションが挟まるため
インデックスが使われなくなってしまいます。
この挙動はEXPLAINではなくEXPLAIN EXTENDEDコマンドを使って、
直後にSHOW WARNINGをすると確認できます。

MySQL 5.5.12以降では、tm列をt1から持ってくる過程で
運よくロジックの発動を回避できているようです。

・対処案1
MySQL 5.5.9から変更できない場合、
SELECT t2.name, t1.tm, t2.v FROM t2, t1 WHERE t2.name = 'n1'
AND t2.tm = CAST(t1.tm AS UNSIGNED) AND DATE(t1.dt) = '2011-08-30';
とすると期待したSQL実行計画になります。
おすすめはしませんが…。

・対処案2
sjisではなくて例えばcp932にすれば直ります。

・対処案3
MySQL 5.5.12以上にすればとりあえずテストケースのクエリは良くなります。
ただ、t2を単独でSELECTすると発動してしまいます。
SELECT * FROM t2 WHERE name = 'n1' AND tm = '20:01';
これに対しては
SELECT * FROM t2 WHERE name = 'n1' AND tm = TIME('20:01');
とすると直ります。ちなみにMySQL 5.5.11では
SELECT * FROM t2 WHERE name = 'n1' AND tm = CAST(TIME('20:01') AS UNSIGNED);
とまでする必要があります。

・対処案4
Bug#62307がVerifyされて直るまで待ちます。


よろしくお願いいたします。

--
平塚貞夫 hiratsuka.sadao@xxxxx


投稿者 xml-rpc : 2011年8月31日 12:33
役に立ちました?:
過去のフィードバック 平均:(0) 総合:(0) 投票回数:(0)
本記事へのTrackback: http://hoop.euqset.org/blog/mt-tb2006.cgi/106025
トラックバック
コメント
コメントする




画像の中に見える文字を入力してください。