2011-01-30 17 views
9

Tôi đang cố gắng buộc SQL của tôi sử dụng hai chỉ mục. Tôi đang tham gia một bảng và tôi muốn họ sử dụng chéo giữa hai chỉ mục. Thuật ngữ cụ thể được Sử dụng giao nhau và đây là một liên kết đến tài liệu MySQL:Buộc MySQL sử dụng hai chỉ mục trên một Tham gia

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

Có cách nào để buộc thực hiện điều này? Truy vấn của tôi đã sử dụng nó (và nó tăng tốc), nhưng bây giờ vì lý do gì nó đã dừng lại.

Đây là JOIN Tôi muốn thực hiện việc này. Hai chỉ số Tôi muốn các truy vấn để sử dụng là scs.CONSUMER_ID_1 và 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

Vui lòng đăng phiên bản MySql, định nghĩa bảng và đầu ra GIẢI THÍCH. –

+0

Ngoài ra, bạn có thể hiển thị toàn bộ truy vấn ... hoặc ít nhất hầu hết phần còn lại có thể không cân nhắc về "bí mật" ... chọn X từ WhatTable ... Tham gia ... Ở đâu ... nhóm theo. .. – DRapp

Trả lời

13

Xem MySQL Documents cho 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 

Như TheScrumMeister đã chỉ ra dưới đây, liệu hai chỉ mục có thể thực sự được sử dụng cùng một lúc hay không.


Đây là ví dụ bạn cần buộc bảng xuất hiện hai lần để kiểm soát việc thực hiện truy vấn và giao lộ.

Sử dụng này để tạo ra một bảng với> 100K hồ sơ, với khoảng 1K hàng phù hợp với các bộ lọc i in (2,3) và 1K hàng phù hợp với 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; 

Khi thực hiện:

select t.* from t1 as t where t.i=2 and t.j=3 or t.i=3 and t.j=2 

bạn nhận được chính xác 8 đối sánh:

+-------+------+------+ 
| 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 | 
+-------+------+------+ 

Sử dụng EXPLAIN trên các truy vấn trên để có được:

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 

Thậm chí nếu chúng ta thêm FORCE INDEX với truy vấn trên hai chỉ số EXPLAIN sẽ trả lại chính xác cùng một điều.

Để làm cho nó thu thập qua hai chỉ số, và sau đó cắt chúng, sử dụng này:

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 

Sử dụng đó truy vấn với explain để có được:

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 

Điều này chứng tỏ rằng các chỉ số đang được sử dụng . Nhưng điều đó có thể hoặc không thể nhanh hơn tùy thuộc vào nhiều yếu tố khác.

+0

Tôi tin rằng nếu giải thích ban đầu chỉ sử dụng 1 trong số các chỉ mục, 'FORCE INDEX' sẽ không ép buộc nó sử dụng ** cả **. –

+0

Tôi nghĩ rằng chỉ số lực mạnh hơn chỉ số sử dụng, tức là nếu nó có thể được sử dụng ở tất cả, nó sẽ được. Vì vậy, sẽ không 1 + 2 được băm cho giao lộ? – RichardTheKiwi

+0

'force index' mạnh hơn và nó cho trình tối ưu hóa truy vấn sử dụng bất kỳ/tất cả các chỉ mục trong danh sách. Vì vậy, nếu kế hoạch ban đầu được sử dụng một bảng quét vì nó quyết định một quét là rẻ hơn, nó sẽ làm việc. tuy nhiên nếu - vì lý do gì đó - trình tối ưu hóa không thể sử dụng cả hai chỉ mục, 'force index ...' sẽ không thực hiện thủ thuật. –

1

MySQL chỉ hỗ trợ sử dụng một chỉ mục duy nhất cho mỗi lần tham gia. Nếu bạn muốn nó sử dụng hai cột làm chỉ mục trong phép nối, bạn nên tạo một chỉ mục duy nhất trên hai cột đó. Lưu ý rằng đây không phải là xấu như nó có vẻ, bởi vì một chỉ số trên (a, b) tăng gấp đôi như là một chỉ số trên chỉ là một.

Xem the MySQL manual

MySQL không thể sử dụng một chỉ số nếu các cột không tạo thành một tiền tố tận cùng bên trái của chỉ số.

+0

Không đúng do tối ưu 'kết hợp chỉ mục'. – Pacerier

Các vấn đề liên quan