क्यों MATCH की तुलना में 4 गुना अधिक तेजी से है ... MySQL में एक पूर्ण सूचकांक पर फिर से?


12

मुझे यह नहीं मिल रहा है।

मुझे इन अनुक्रमणिकाओं के साथ एक तालिका मिली है

PRIMARY     post_id
INDEX       topic_id
FULLTEXT    post_text

तालिका में (केवल) 346 000 पंक्तियाँ हैं। मैं 2 प्रश्न करने की कोशिश कर रहा हूं।

SELECT post_id 
FROM phpbb_posts 
WHERE topic_id = 144017 
AND post_id != 155352 
AND MATCH(post_text) AGAINST('http://rapidshare.com/files/5494794/photo.rar')

जबकि 4.05 सेकंड लगते हैं

SELECT post_id 
FROM phpbb_posts 
WHERE topic_id=144017 
AND post_id != 155352 
AND post_text LIKE ('%http://rapidshare.com/files/5494794/photo.rar%')

0.027 सेकंड लेता है।

EXPLAIN से पता चलता है कि केवल अंतर fulltextसंभव__में है ( पोस्ट_टेक्स्ट शामिल है, LIKEनहीं)

यह वास्तव में अजीब है।

इसके पीछे क्या है? पृष्ठभूमि में क्या हो रहा है? LIKEजब सूचकांक का उपयोग नहीं किया जाता है और अपने सूचकांक का उपयोग करते समय FULLTEXT इतना धीमा कैसे हो सकता है?

Update1:

वास्तव में अब लगभग 0.5 सेकंड लगते हैं, हो सकता है कि टेबल को लॉक कर दिया गया था, लेकिन फिर भी, जब मैं प्रोफाइलिंग चालू करता हूं तो यह दिखाता है कि फुलटिट इंस्टीट्यूशन ने 0.2 सेकंड का समय लिया। क्या हो रहा है?

मैं अपनी तालिका को LIKE10x सेकंड के साथ पूर्णांक केवल 2x के साथ क्वेरी कर सकता हूं

UPDATE2:

आश्चर्य!

mysql> SELECT post_id FROM phpbb_posts WHERE post_id != 2 AND topic_id = 6 AND MATCH(post_text) AGAINST ('rapidshare.com');
Empty set (0.04 sec)

तो मैं पूछ रहा हूँ, यह कैसे संभव है?

साथ ही,

SELECT count(*) FROM phpbb_posts WHERE MATCH(post_text) AGAINST ('rapidshare.com')

वास्तव में धीमा है। किसी भी टूट फुलटेक्स्ट हो सकता है?

Update3:

क्या बकवास है?

SELECT forum_id, post_id, topic_id, post_text  FROM phpbb_posts  WHERE MATCH(post_text) AGAINST ('rapidshare.com') LIMIT 0, 30;

जबकि 0.27s लगते हैं

SELECT count(*) FROM phpbb_posts  WHERE MATCH(post_text) AGAINST ('rapidshare.com') LIMIT 0, 30;

30 सेकंड से अधिक समय लगता है! यहाँ क्या गलत हो रहा है?


क्या दोनों के बीच प्रतिक्रिया समय कई रन से अधिक है? मुझे लगता है कि डिस्क कैशिंग खेलने में आ रहा है, जहां पहला "धीमा" परीक्षण राम में आवश्यक सभी डेटा को लोड करता है, इसलिए दूसरा "तेज़" क्वेरी अच्छी तरह से तेज़ है।
18x12 में atxdba

केवल SQL_NO_CACHE के साथ प्रश्नों का परीक्षण करें ।
20/07 पर mgutt

यह बहुत पुराना प्रश्न / उत्तर है। उन दिनों के बाद से mysql / mariadb से कोई प्रगति?
रोमन सूसी

1
सावधानी: इस प्रश्नोत्तर के समय का अर्थ है कि यह केवल MyISAM के बारे में बात कर रहा है। InnoDB के लिए इसकी प्रयोज्यता प्रश्न में है।
रिक जेम्स

@RomanSusi - क्या आप एक नया प्रश्न शुरू करना चाहेंगे जिसका उद्देश्य InnoDB है?
रिक जेम्स

जवाबों:


2

मुझे लगता है कि समस्या फुलटैक्स सूचकांक की उपस्थिति से ही हो सकती है।

हर बार जब फुलटेक्स्ट इंडेक्स वाली क्वेरी होती है, तो MySQL क्वेरी ऑप्टिमाइज़र क्वेरी को फुल टेबल स्कैन में मिटा देता है। मैंने वर्षों से इसे देखा है। मैंने FULLTEXT इंडेक्स में इस सबसे ट्रिफ़लिंग व्यवहार के बारे में एक पुरानी पोस्ट भी लिखी थी

आपको दो काम करने की आवश्यकता हो सकती है:

  1. फिर से क्वेरी करें ताकि FULLTEXT इंडेक्स MySQL क्वेरी ऑप्टिमाइज़र को भ्रम की स्थिति में न फेंके
  2. अतिरिक्त इंडेक्स जोड़ें जो रिफैक्ट की गई क्वेरी का ठीक से समर्थन करेगा

प्रश्न का उत्तर दें

यहाँ आपकी मूल क्वेरी है

SELECT post_id  
FROM phpbb_posts  
WHERE topic_id = 144017  
AND post_id != 155352  
AND MATCH(post_text) AGAINST('http://rapidshare.com/files/5494794/photo.rar') 

आपको इस तरह से क्वेरी को रिफलेक्टर करना होगा:

SELECT subqueryA.post_id
FROM
(
    SELECT post_id FROM phpbb_posts
    WHERE topic_id = 144017
    AND post_id != 155352
) subqueryA
INNER JOIN
(
    SELECT post_id FROM phpbb_posts
    WHERE MATCH(post_text) AGAINST('http://rapidshare.com/files/5494794/photo.rar')
) subqueryB
USING (post_id);

एक नया सूचकांक बनाएँ

समर्थन करने के लिए आपको एक सूचकांक की आवश्यकता होगी subqueryA। आपके पास पहले से ही एक इंडेक्स है topic_id। आपको इसे इस प्रकार बदलना होगा:

ALTER TABLE phpbb_posts ADD INDEX topic_post_ndx (topic_id,post_id);
ALTER TABLE phpbb_posts DROP INDEX topic_id;

कोशिश करो !!!

अद्यतन 2012-03-19 13:08 EDT

पहले यह एक कोशिश करो

SELECT post_id FROM
(
    SELECT * FROM phpbb_posts
    WHERE topic_id = 144017
    AND post_id != 155352
) A;

यदि यह तेजी से चलता है और छोटी संख्या में पंक्तियाँ लौटाता है, तो इस नेस्टेड सबक्वेरी को आज़माएँ:

SELECT post_id FROM
(
    SELECT * FROM phpbb_posts
    WHERE topic_id = 144017
    AND post_id != 155352
) A
WHERE MATCH(post_text) AGAINST('http://rapidshare.com/files/5494794/photo.rar');

अद्यतन 2012-03-19 13:11 EDT

इसके चलने के समय की तुलना करें:

SELECT count(*) FROM phpbb_posts  WHERE MATCH(post_text) AGAINST ('rapidshare.com') LIMIT 0, 30;

इसके साथ

SELECT count(*) FROM phpbb_posts WHERE 1 = 1;

यदि रनिंग टाइम समान है, तो हर पंक्ति पर MATCH क्लॉज निष्पादित किया जा रहा है। जैसा कि मैंने पहले उल्लेख किया है, फुलटेक्स्ट इंडेक्स का उपयोग करके MySQL क्वेरी ऑप्टिमाइज़र द्वारा प्रयास किए गए और योगदान किए गए किसी भी लाभ को कम करने के लिए जाता है।


इसलिए आप यह कहना चाहते हैं कि मेरी क्वेरी वास्तव में संपूर्ण तालिका को स्कैन करती है क्योंकि topic_id और post_idइसे भ्रमित करता है? इन स्तंभों (index_id, post_id) पर अनुक्रमणिका के बिना भी LIKE क्वेरी क्यों काम करती है? MYSQL topic_id = 144017 AND post_id != 155352इन परिणामों के माध्यम से सिर्फ समझदारी से चयन क्यों नहीं करता ? और क्या होगा अगर 100k पंक्तियों में मेरा फुलटेक्स सर्च स्ट्रिंग शामिल है post_text? क्या यह उन सभी का चयन नहीं करेगा?
उत्पत्ति

वास्तव में मैं और भी अधिक भ्रमित हूँ। LIKE '% text%' इंडेक्स का उपयोग नहीं करता है, इसका मतलब है कि यह पूरी टेबल को स्कैन करता है, तो यह इतनी जल्दी क्यों है?
उत्पत्ति 10

कृपया मेरे अद्यतन को देखें , मुझे लगता है कि आप इसे वास्तव में तेजी से हल करेंगे। यदि आप इसे हल करते हैं तो मैं आपको अपना प्रतिनिधि देने जा रहा हूं।
उत्पत्ति 10

आपके दूसरे अपडेट का जवाब। दूसरी क्वेरी 0.01ms से कम में चली गई, पहला वाला पूरा नहीं हुआ। आपने क्यों कहा "यदि रनिंग टाइम समान है, तो हर पंक्ति पर MATCH क्लॉज निष्पादित किया जा रहा है।" ? क्या यह इसके बिल्कुल विपरीत नहीं होना चाहिए? यदि आप यहाँ देखते हैं , तो आप देखेंगे कि मैं इस समस्या के साथ अकेला नहीं हूँ
उत्पत्ति

आपके पहले अपडेट का जवाब देना। पहली क्वेरी 0.01ms, 0 पंक्तियों में चली गई, दूसरा एक "कॉलम सूची से मेल खाते हुए पूर्णांक सूचकांक नहीं मिल सकता है"। हालाँकि, 2 सबक्वेरी के साथ आपकी क्वेरी पूरी तरह से काम करती है!
उत्पत्ति
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.