2011-01-30 20 views
9

मैं अपने एसक्यूएल को दो इंडेक्स का उपयोग करने के लिए मजबूर करने की कोशिश कर रहा हूं। मैं एक टेबल में शामिल हो रहा हूं और मैं चाहता हूं कि वे दो इंडेक्स के बीच क्रॉस का उपयोग करें। विशिष्ट शब्द एक दूसरे को काटना का उपयोग करना और यहां MySQL प्रलेखन के लिए एक लिंक है:फोर्स माईएसक्यूएल को 0 इंडेक्स पर दो इंडेक्स का उपयोग करने के लिए फोर्स

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 संस्करण, तालिका परिभाषाएं और EXPLAIN आउटपुट पोस्ट करें। –

+0

इसके अतिरिक्त, क्या आप पूरी क्वेरी ... या कम से कम बाकी को दिखा सकते हैं जो शायद "गोपनीय" पर विचार न करें ... व्हाटटेबल से एक्स का चयन करें ... शामिल हों ... कहां ... समूह द्वारा। .. – DRapp

उत्तर

13

देखें 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 नीचे बताया गया है, यह आपके डेटा पर निर्भर करता है, चाहे के इंडेक्स वास्तव में एक ही बार में इस्तेमाल किया जा सकता।


यहां एक उदाहरण दिया गया है जहां आपको क्वेरी निष्पादन और चौराहे को नियंत्रित करने के लिए तालिका को दो बार प्रकट करने की आवश्यकता है। इस फिल्टर 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 | 
+-------+------+------+ 

का उपयोग करें क्वेरी पर 0 से ऊपर पाने के लिए:

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 

यहां तक ​​कि अगर हम एक के इंडेक्स EXPLAIN पर सवाल के FORCE INDEX जोड़ने सटीक एक ही बात वापस आ जाएगी।

यह इंडेक्स भर में इकट्ठा कर, और फिर उन्हें एक दूसरे को काटना करने के लिए, इस का उपयोग करें: प्राप्त करने के लिए

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 

यह साबित होता है कि अनुक्रमित किया जा रहा है । लेकिन यह कई अन्य कारकों के आधार पर तेजी से हो सकता है या नहीं भी हो सकता है।

+0

मेरा मानना ​​है कि मूल व्याख्या केवल इंडेक्स में से 1 का उपयोग कर रही थी, 'फोर्स इंडेक्स' ** ** ** दोनों का उपयोग करने के लिए मजबूर नहीं होगी। –

+0

मैंने सोचा कि बल सूचकांक उपयोग सूचकांक से अधिक मजबूत है, यानी अगर इसका उपयोग किया जा सकता है, तो यह होगा। तो चौराहे के लिए 1 + 2 धोया नहीं जाएगा? – RichardTheKiwi

+0

'बल सूचकांक' मजबूत है, और यह क्वेरी ऑप्टिमाइज़र को सूची में किसी भी/सभी अनुक्रमणिका का उपयोग करने के लिए कहता है। इसलिए यदि मूल योजना ने टेबल स्कैन का उपयोग किया क्योंकि उसने फैसला किया कि स्कैन सस्ता है, तो यह काम करेगा। हालांकि अगर - किसी भी कारण से - अनुकूलक दोनों इंडेक्स का उपयोग करने में असमर्थ था, 'बल सूचकांक ...' चाल नहीं करेगा। –

1

MySQL केवल प्रति शेयर एक इंडेक्स का उपयोग करने का समर्थन करता है। यदि आप इसे दो कॉलमों को शामिल करने के सूचकांक के रूप में उपयोग करना चाहते हैं, तो आपको उन दो स्तंभों पर एक एकल अनुक्रमणिका बनाना चाहिए। ध्यान दें कि यह उतना बुरा नहीं है जितना लगता है, क्योंकि एक इंडेक्स (ए, बी) केवल एक पर इंडेक्स के रूप में दोगुना हो जाता है।

देखें the MySQL manual

MySQL एक सूचकांक उपयोग नहीं कर सकते, तो कॉलम सूचकांक का एक वाम-पंथी उपसर्ग फार्म नहीं है।

+0

'इंडेक्स विलय 'अनुकूलन के कारण सही नहीं है। – Pacerier