JOINよりIN

Date 2006-06-04 04:32:00 | Category: PHP

in englishin japanese
MySQLの特徴の一つに、「単純なクエリでは圧倒的に速いが、複雑なクエリだとそうでもない」が挙げられます。

そのため、LAMPアプリケーションの設計では、クエリの回数を抑えることよりも、各クエリをバラバラにして、なるべく単純なクエリにすることが、速度向上の近道のようです。

例えば、「カテゴリー対グループという権限設定のついたアイテムを検索する」なんてありがちなケースを考えます。

CREATE TABLE cat (
  `cid` int NOT NULL default 0,
  `name` varchar(255) NOT NULL default '',
  PRIMARY KEY (cid)
) TYPE=MyISAM ;

CREATE TABLE cat_perm (
  `cid` int NOT NULL default 0,
  `gid` int NOT NULL default 0,
  PRIMARY KEY (cid,gid)
) TYPE=MyISAM ;

CREATE TABLE item (
  `id` int NOT NULL default 0,
  `cid` int NOT NULL default 0,
  `name` varchar(255) NOT NULL default '',
  PRIMARY KEY (id),
  KEY (cid)
) TYPE=MyISAM ;


こんな構造の場合、SQL書きを得意としている人間は、ついつい、

SELECT item.* FROM item LEFT JOIN cat_perm ON cat_perm.cid=item.cid WHERE cat_perm.gid=1;

なんてクエリを発行しがちですが、少なくともMySQL的には効率が悪いのです。


SELECT cid FROM cat_perm WHERE gid=1;

として、いったんcidを一通り得てから、

SELECT * FROM item WHERE cid IN (cid一覧);

と2回に分けることで、実はとてもMySQLの効率は良くなります。

もちろん、「cidを一通り」得てIN用の文字列を用意する部分の実行効率がどれほどであるかによってトータルのパフォーマンス違ってくるでしょうが、ざっとベンチマークをとった限り、通常のLAMP環境では、やはり後者の方が速い、という結果が得られました。(「カテゴリー数」が増えて、INの部分がかなり長いケースでも結果は同じ)

実際のケースでは、アイテムに対するカテゴリーは十分に小さく、逆に、権限テーブルはずっと複雑になりがちなので、その差はもっと開くと思います。

JOINよりもIN

標語としても良くできてますね
--------------------
(2006/06/06追記)
このベンチマーク自体は問題ないのですが、比較する相手が悪いという指摘を受けました。
確かにその通りだったので、訂正記事の方も参照してください。




You can read more news at PEAK XOOPS.
http://xoops.peak.ne.jp

The URL for this story is:
http://xoops.peak.ne.jp/md/news/index.php?page=article&storyid=122