Заставить MySQL использовать два индекса на соединении

Я пытаюсь заставить MySQL использовать два индекса. Я присоединяюсь к таблице, и я хочу использовать крест между двумя индексами. Конкретный термин использует intersect и вот ссылка на документацию MySQL:

http://dev.mysql.com/doc/refman/5.0/en/index-merge-optimization.html

есть ли способ заставить эту реализацию? Мой запрос использовал его (и он ускорил материал), но теперь по какой-то причине он остановился.

здесь соединение, на котором я хочу это сделать. Два индекса, которые я хочу использовать в запросе, - это 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

2 ответов


см. документы MySQL для FORCE INDEX.

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, это зависит от ваших данных, могут ли фактически использоваться два индекса одновременно.


Вот пример, где вам нужно заставить таблицу появиться дважды, чтобы контролировать выполнение запроса и пересечение.

используйте это, чтобы создать таблицу с > 100k записей, с примерно 1K строк, соответствующих фильтр i in (2,3) и соответствие строк 1K j in (2,3):

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

даже если добавить FORCE INDEX запрос по двум индексам EXPLAIN вернет то же самое.

чтобы собрать его по двум индексам, а затем пересечь их, используйте это:

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 to получить:

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 поддерживает только использование одного индекса на соединение. Если вы хотите использовать два столбца в качестве индексов в соединении, вы должны создать один индекс над этими двумя столбцами. Обратите внимание, что это не так плохо, как кажется, потому что индекс над (a, b) удваивается как индекс над a.

посмотреть руководство MySQL

MySQL не может использовать индекс, если столбцы не образуют левый префикс индекса.