Заставить 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 не может использовать индекс, если столбцы не образуют левый префикс индекса.