2010年7月 1日

[mysql 15357] Re: 検索条件カラムを縦持ちにした場合の検索の性能について。

奥野です。

独立したインデックスの場合、condテーブルが駆動表になれば問題ないんですが、
内部表になってしまうと結合のためにa_idインデックスを利用するため
condインデックスが効きません。その場合、(a_id, cond1)というような
複合インデックスが必要になります。しかしそのようなインデックスしか存在しないと
今度はcond単体で検索することが出来なくなるため、それとは別に
独立したインデックスもやはり必要です。condごとに単体のインデックスと

複合インデックスをあわせもつのは、躊躇しますよね。

なぜこんな面倒なことになるかというと、MySQLではINTERSECTをサポートしていない
からですね。(bug #31336)Index merge(intersect)という検索アルゴリズムが
ありますが、このような範囲検索では効きません。

とりあえず、考えられる方策としては、

・テーブルスキャン覚悟でJOINではなくANDで条件を結合させる。
 ※JOINごとにスキャンが発生するよりは遙かにマシですね。
・色々覚悟で体のインデックスと複合インデックスをあわせもつ。
・condごとにテーブルを分ける。(どっちにしろインデックスは必要です。)
・サブクエリを利用する。(下記参照)

サブクエリについては、condごとにかなり行数を絞り込めるようなら試して見る
価値があると思います。

SELECT a_id, o.val
FROM a
JOIN (SELECT a_id FROM cond WHERE cond1 BETWEEN 00110 AND 00120) AS c1 USING (a_id)
JOIN (SELECT a_id FROM cond WHERE cond2 BETWEEN 00270 AND 00290) AS c2 USING (a_id)
JOIN o USING (a_id);

ではでは。
--
奥野 幹也
http://www.google.com/profiles/mikiya.okuno
http://nippondanji.blogspot.com/
http://twitter.com/nippondanji


On 28/06/2010, at 11:35 PM, とみたまさひろ wrote:

> とみたです。
>
> On Mon, 28 Jun 2010 21:38:23 +0900
> MATSUNAGA Ichiro <vikke.bsd@xxxxx> wrote:
>
>> この状態で、他のtable(other)をjoinしつつ、cond1(001)が10あるいは20、かつcond2(002)が70あるいは80あるいは90の条件を見たすrecordが欲しい場合、
>> select a_id, o.val
>> from
>> a
>> inner join cond c1 using(a_id)
>> inner join cond c2 using(a_id)
>> inner join other o using(o_id)
>> where
>> c1.cond between 00110 and 00120
>> and c2.cond between 00270 and 00290;
>> というsqlを実行してみたのですが、結構重い状態です。
>
> 次のように cond カラムに独立したインデックスを張ってみてはいかがでしょうか。
>
> create table cond (
> a_id int(10) not null,
> cond int(5) not null,
> primary key (a_id, cond),
> index (cond)
> )
>
> --
> とみたまさひろ <tommy@xxxxx>
> 日本MySQLユーザ会 http://www.mysql.gr.jp
>

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




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