|
我试图强迫MySQL使用两个索引。我正在加入一个表,我想利用两个索引之间的交叉。具体术语是“使用相交”,这是指向MySQL文档的链接:( @# I8 R4 @6 q/ L% G
http://dev.mysql.com/doc/refman/5.0/zh-CN/index-merge-
' @1 k# w T2 s# D0 o P3 q8 P4 qoptimization.html
: Y# E) b. F( B4 P有什么办法可以强制实施吗?我的查询正在使用它(并且它加快了速度),但是现在无论出于何种原因它都停止了。
! j4 n8 K& ]9 j* \' E7 J2 @3 Y这是我要继续执行的JOIN。我希望查询使用的两个索引是scs.CONSUMER_ID_1和scs_CONSUMER_ID_2
# c! j9 G' O4 P- x+ f0 m6 G2 lJOIN survey_customer_similarity AS scs
* ~( B+ T- w; K4 a- S) I3 g ON cr.CONSUMER_ID=scs.CONSUMER_ID_2
9 G) ?- x; f4 L9 j+ e# o. i0 U" g AND cal.SENDER_CONSUMER_ID=scs.CONSUMER_ID_1
# [: b9 v. o: A OR cr.CONSUMER_ID=scs.CONSUMER_ID_1
4 j* q7 z* Z7 R8 q7 f$ i$ m* I9 | AND cal.SENDER_CONSUMER_ID=scs.CONSUMER_ID_2
& x7 o% v4 a! m$ B* Y5 f3 H" m ! [+ v# q) U+ G& U8 ^% `' x
解决方案:7 f; X5 N$ B4 f! i- g( E% W
8 g: @& t6 q/ ~8 r% D
8 d/ Z0 P J( R0 C
* j2 W2 N9 ^8 z2 g. B
参见MySQL文档FORCE INDEX。- A. e) U5 o3 b; w
JOIN survey_customer_similarity AS scs f |" ^9 v( u' N, [9 z- h
FORCE INDEX (CONSUMER_ID_1,CONSUMER_ID_2) q m: R8 g4 M! z% |
ON
; I% _! L6 t t" t+ jcr.CONSUMER_ID=scs.CONSUMER_ID_2
! T9 i' I) x H2 t* BAND cal.SENDER_CONSUMER_ID=scs.CONSUMER_ID_1
g$ V* `9 }( v# ROR cr.CONSUMER_ID=scs.CONSUMER_ID_1
! }9 m6 v% U. H. i% m, L* F3 hAND cal.SENDER_CONSUMER_ID=scs.CONSUMER_ID_2
! }8 b+ ]" C, g7 W5 }- j6 `0 j3 I/ w正如TheScrumMeister在下面指出的那样,它是否可以同时实际使用两个索引取决于您的数据。0 y- v9 e' K0 R$ ^7 x
( N3 X1 f3 e6 r7 T g* P
这是一个示例,您需要强制该表出现两次以控制查询的执行和交集。, m( D0 O; F4 s3 J
使用它来创建一个包含100K条记录的表,其中约1K行与过滤条件匹配,i in (2,3)而1K行与j in (2,3)以下条件匹配:$ R( _, e5 K/ B* h) P/ }2 |
drop table if exists t1;/ x" R5 o3 Y2 f; E9 `4 L4 q
create table t1 (id int auto_increment primary key, i int, j int);$ |1 S5 X! G- E( ?: t, B
create index ix_t1_on_i on t1(i);
0 E: |9 g: d& Z5 o; N% ecreate index ix_t1_on_j on t1(j);
! A `2 i, j" W, F) Einsert into t1 (i,j) values (2,2),(2,3),(4,5),(6,6),(2,6),(2,7),(3,2);
- w3 y; I+ o J( \insert into t1 (i,j) select i*2, j*2+i from t1;
9 w! @# i% ?5 A8 A+ o) e9 vinsert into t1 (i,j) select i*2, j*2+i from t1;
9 Z" R3 `4 Y# G, O, Y+ {insert into t1 (i,j) select i*2, j*2+i from t1;$ N" c( d9 Z0 ^' c p9 O. F; a
insert into t1 (i,j) select i*2, j*2+i from t1;+ S+ y2 r6 z/ _3 n
insert into t1 (i,j) select i*2, j*2+i from t1;
& X' \& \; S5 m: O$ d, p, j% M+ Dinsert into t1 (i,j) select i*2, j*2+i from t1;+ m6 t3 b- }* a5 W7 B
insert into t1 (i,j) select i*2, j*2+i from t1;
0 @) U) }5 D8 [$ \- X5 w3 @0 Rinsert into t1 (i,j) select i*2, j*2+i from t1;2 f( ^( P2 W$ q+ d1 E
insert into t1 (i,j) select i*2, j*2+i from t1;6 q, j% p7 _8 J' W. N {! k
insert into t1 (i,j) select i*2, j*2+i from t1;6 v+ B C" P7 f2 w
insert into t1 (i,j) select i*2, j*2+i from t1;: L: N; n% D# {- a6 x! A9 r
insert into t1 (i,j) select i*2, j*2+i from t1;
% c5 N3 t. t# n6 Winsert into t1 (i,j) select i, j from t1;4 _+ e) e2 \1 |: F
insert into t1 (i,j) select i, j from t1;
( h; `( }% Z0 U8 Ginsert into t1 (i,j) select 2, j from t1 where not j in (2,3) limit 1000;
( ^0 l) c4 o) [1 Zinsert into t1 (i,j) select i, 3 from t1 where not i in (2,3) limit 1000;
" l% V' u3 y5 O ^进行时:8 j% n- ]. X0 D; Q2 ^; Q B
select t.* from t1 as t where t.i=2 and t.j=3 or t.i=3 and t.j=2
4 {9 z. A1 O3 L# h9 `) ?您将获得8场匹配的比赛:
# H+ D6 s3 B* A5 i5 W6 L+-------+------+------+
* K7 R" D e! }+ G2 [/ m# X1 G| id | i | j |
7 M: v2 L; |1 q' u6 o+ ^* f, o+-------+------+------+
0 i3 d. y2 n% E| 7 | 3 | 2 |
. c, V1 C% C' c% K4 n) O| 28679 | 3 | 2 |
7 R! p( y9 m1 w. ~/ ~$ z| 57351 | 3 | 2 |
7 n1 g9 Q) c+ x| 86023 | 3 | 2 |! D% \8 v4 b) h0 p8 C ~' y
| 2 | 2 | 3 |- O4 g: I1 a* k
| 28674 | 2 | 3 |3 e4 }" U0 g! H1 I9 I
| 57346 | 2 | 3 |2 h3 y0 h! A( z2 q$ Z8 q1 Z2 f
| 86018 | 2 | 3 |( j0 v h( J3 {6 e# E }
+-------+------+------+. g! `" L: l% @$ Y, \
EXPLAIN在上面的查询中使用以获取:* Y1 l# ~2 e3 i
id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra
+ F- n! d! M9 v. i1 | SIMPLE | t | range | ix_t1_on_i,ix_t1_on_j | ix_t1_on_j | 5 | NULL | 1012 | Using where
* H/ E: G- D' R" k即使我们FORCE INDEX在两个索引上添加查询,EXPLAIN也将返回 完全相同的内容 。
4 r; h9 z+ A. e3 Y& S2 Z5 x要使其跨两个索引收集,然后相交,请使用以下命令:
# s& E5 f( t! g# Tselect t.* from t1 as a force index(ix_t1_on_i)/ Y/ P# t k; W
join t1 as b force index(ix_t1_on_j) on a.id=b.id
* y* q% L. ^; N. \5 }where a.i=2 and b.j=3 or a.i=3 and b.j=2
9 |! ~5 T& k8 C1 u6 i使用该查询explain可获取:4 S, U/ B* l8 C% d% b$ H/ @
id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra
/ ]7 N3 V" H& S: L2 t0 i& v& N1 | SIMPLE | a | range | ix_t1_on_i | ix_t1_on_i | 5 | NULL | 1019 | Using where" u5 t2 y1 h* R$ p/ L, N
1 | SIMPLE | b | range | ix_t1_on_j | ix_t1_on_j | 5 | NULL | 1012 | Using where; Using index
% Y0 b5 K, P0 q5 v' }+ N% v; ~这证明正在使用索引。但这可能会更快,也可能不会更快,这取决于许多其他因素。 |
|