MySQLに2つのインデックスを使用させようとしています。テーブルを結合していて、2つのインデックス間のクロスを利用したいと思います。具体的な用語は「交差の使用」であり、MySQLのドキュメントへのリンクは次のとおりです。
http://dev.mysql.com/doc/refman/5.0/en/index-merge-optimization.html
この実装を強制する方法はありますか?私のクエリはそれを使用していました(そしてそれはものをスピードアップしました)、しかし今何らかの理由でそれは停止しました。
これが私がこれをやりたいJOINです。クエリで使用する2つのインデックスは、scs.CONSUMER_ID_1とscs_CONSUMER_ID_2です。
JOIN survey_customer_similarity AS scs
ON cr.CONSUMER_ID=scs.CONSUMER_ID_2
AND cal.SENDER_CONSUMER_ID=scs.CONSUMER_ID_1
OR cr.CONSUMER_ID=scs.CONSUMER_ID_1
AND cal.SENDER_CONSUMER_ID=scs.CONSUMER_ID_2
_FORCE INDEX
_ についてはMySQLドキュメントを参照してください。
_JOIN survey_customer_similarity AS scs
FORCE INDEX (CONSUMER_ID_1,CONSUMER_ID_2)
ON
cr.CONSUMER_ID=scs.CONSUMER_ID_2
AND cal.SENDER_CONSUMER_ID=scs.CONSUMER_ID_1
OR cr.CONSUMER_ID=scs.CONSUMER_ID_1
AND cal.SENDER_CONSUMER_ID=scs.CONSUMER_ID_2
_
TheScrumMeisterが以下で指摘しているように、2つのインデックスを実際に同時に使用できるかどうかは、データによって異なります。
これを使用して、フィルターi in (2,3)
に一致する約1K行とj in (2,3)
に一致する1K行を含む、> 100Kレコードのテーブルを作成します。
_drop table if exists t1;
create table t1 (id int auto_increment primary key, i int, j int);
create index ix_t1_on_i on t1(i);
create index ix_t1_on_j on t1(j);
insert into t1 (i,j) values (2,2),(2,3),(4,5),(6,6),(2,6),(2,7),(3,2);
insert into t1 (i,j) select i*2, j*2+i from t1;
insert into t1 (i,j) select i*2, j*2+i from t1;
insert into t1 (i,j) select i*2, j*2+i from t1;
insert into t1 (i,j) select i*2, j*2+i from t1;
insert into t1 (i,j) select i*2, j*2+i from t1;
insert into t1 (i,j) select i*2, j*2+i from t1;
insert into t1 (i,j) select i*2, j*2+i from t1;
insert into t1 (i,j) select i*2, j*2+i from t1;
insert into t1 (i,j) select i*2, j*2+i from t1;
insert into t1 (i,j) select i*2, j*2+i from t1;
insert into t1 (i,j) select i*2, j*2+i from t1;
insert into t1 (i,j) select i*2, j*2+i from t1;
insert into t1 (i,j) select i, j from t1;
insert into t1 (i,j) select i, j from t1;
insert into t1 (i,j) select 2, j from t1 where not j in (2,3) limit 1000;
insert into t1 (i,j) select i, 3 from t1 where not i in (2,3) limit 1000;
_
行うとき:
_select t.* from t1 as t where t.i=2 and t.j=3 or t.i=3 and t.j=2
_
正確に8つの一致が得られます。
_+-------+------+------+
| id | i | j |
+-------+------+------+
| 7 | 3 | 2 |
| 28679 | 3 | 2 |
| 57351 | 3 | 2 |
| 86023 | 3 | 2 |
| 2 | 2 | 3 |
| 28674 | 2 | 3 |
| 57346 | 2 | 3 |
| 86018 | 2 | 3 |
+-------+------+------+
_
上記のクエリでEXPLAIN
を使用して、以下を取得します。
_id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra
1 | SIMPLE | t | range | ix_t1_on_i,ix_t1_on_j | ix_t1_on_j | 5 | NULL | 1012 | Using where
_
2つのインデックスのクエリに_FORCE INDEX
_を追加しても、EXPLAIN
はまったく同じものを返します。
2つのインデックスにまたがって収集し、それらを交差させるには、次を使用します。
_select t.* from t1 as a force index(ix_t1_on_i)
join t1 as b force index(ix_t1_on_j) on a.id=b.id
where a.i=2 and b.j=3 or a.i=3 and b.j=2
_
そのクエリをexplain
とともに使用して、以下を取得します。
_id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra
1 | SIMPLE | a | range | ix_t1_on_i | ix_t1_on_i | 5 | NULL | 1019 | Using where
1 | SIMPLE | b | range | ix_t1_on_j | ix_t1_on_j | 5 | NULL | 1012 | Using where; Using index
_
これは、インデックスが使用されていることを示しています。しかし、他の多くの要因に応じて、それが速い場合とそうでない場合があります。
MySQLは、結合ごとに1つのインデックスの使用のみをサポートします。結合のインデックスとして2つの列を利用する場合は、これら2つの列の上に1つのインデックスを作成する必要があります。 (a、b)のインデックスは、aだけのインデックスを兼ねているため、これは見た目ほど悪くはないことに注意してください。
MySQLマニュアル を参照してください
列がインデックスの左端のプレフィックスを形成しない場合、MySQLはインデックスを使用できません。