पूर्ण पाठ खोज परिणाम 'फुलटेक्ट आरंभीकरण' में खर्च हुए समय की एक बड़ी मात्रा में होता है


12

मैं वर्तमान में स्टैक ओवरफ्लो की टिप्पणियों के डेटा डंप के खिलाफ कुछ प्रश्नों को चलाने की कोशिश कर रहा हूं। यहाँ स्कीमा कैसा दिखता है:

CREATE TABLE `socomments` (
  `Id` int(11) NOT NULL,
  `PostId` int(11) NOT NULL,
  `Score` int(11) DEFAULT NULL,
  `Text` varchar(600) NOT NULL,
  `CreationDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `UserId` int(11) NOT NULL,
  PRIMARY KEY (`Id`),
  KEY `idx_socomments_PostId` (`PostId`),
  KEY `CreationDate` (`CreationDate`),
  FULLTEXT KEY `Text` (`Text`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

मैंने इस क्वेरी को तालिका के विरुद्ध चलाया, और यह अविश्वसनीय रूप से धीमी गति से चली (इसमें 29 मिलियन पंक्तियाँ हैं, लेकिन इसमें एक पूर्ण-पाठ अनुक्रमणिका है):

SELECT *
FROM socomments
WHERE MATCH (Text) AGAINST ('"fixed the post"' IN BOOLEAN MODE)

इसलिए मैंने इसे प्रोफाइल किया, जिसके परिणाम हैं:

|| Status                     || Duration ||
|| starting                   || 0.000058 ||
|| checking permissions       || 0.000006 ||
|| Opening tables             || 0.000014 ||
|| init                       || 0.000019 ||
|| System lock                || 0.000006 ||
|| optimizing                 || 0.000007 ||
|| statistics                 || 0.000013 ||
|| preparing                  || 0.000005 ||
|| FULLTEXT initialization    || 207.1112 ||
|| executing                  || 0.000009 ||
|| Sending data               || 0.000856 ||
|| end                        || 0.000004 ||
|| query end                  || 0.000004 ||
|| closing tables             || 0.000006 ||
|| freeing items              || 0.000059 ||
|| logging slow query         || 0.000037 ||
|| cleaning up                || 0.000046 ||

जैसा कि आप देख सकते हैं, यह फुलटेक्ट आरंभीकरण में एक लंबा समय बिताता है। क्या यह सामान्य है? यदि नहीं, तो मैं इसे कैसे ठीक करूँगा?


विचार: एक 2 तालिका बनाएँ जहाँ आप प्रत्येक 1.000 टिप्पणियाँ एक पाठ क्षेत्र में रखते हैं। अब आप इस दूसरी तालिका में पहले खोजते हैं और आप उदाहरण के लिए id_group 2और id_group 23। इसके साथ आपकी मुख्य तालिका के अंदर आपकी खोज और आपकी क्वेरी को २.००० से २.९९ और २३.०० से २३.९९ तक सीमित कर देता है। निश्चित रूप से 2 के रूप में आवश्यकतानुसार अधिक परिणाम मिलेंगे क्योंकि आप नए कीवर्ड संयोजन बनाते हुए सभी टिप्पणियों को मिलाते हैं, लेकिन अंत में इसे पूरी चीज़ को गति देना चाहिए। बेशक यह डिस्क स्थान उपयोग को दोगुना करता है। नई टिप्पणियाँ जाना चाहिए CONCAT'ed समूह-मेज पर।
mgutt

जवाबों:


5

दूसरों ने इसे एक परेशानी वाली स्थिति पाया है

चूंकि MySQL डॉक्युमेंटेशन इस थ्रेड स्टेट पर बहुत ट्रिब्यूट है

FULLTEXT आरंभीकरण

सर्वर एक प्राकृतिक-भाषा पूर्ण-पाठ खोज करने की तैयारी कर रहा है।

आपका एकमात्र सहारा कम डेटा के साथ तैयारी करना होगा। कैसे ?

शुक्रिया # 1

अपनी क्वेरी को फिर से देखें। यह सभी स्तंभों का चयन कर रहा है। मैं केवल आईडी कॉलम को इकट्ठा करने के लिए क्वेरी को रिफलेक्टर करूंगा socomments। फिर, उन पुनर्प्राप्त आईडी को वापस socommentsतालिका में शामिल करें।

SELECT B.* FROM
(SELECT id FROM socomments
WHERE MATCH (Text) AGAINST ('"fixed the post"' IN BOOLEAN MODE)) A
LEFT JOIN socomments B USING (id);

यह एक बदसूरत अतिरिक्त योजना का उत्पादन कर सकता है, लेकिन मुझे लगता है कि रूपरेखा बेहतर के लिए बदल जाएगी। मूल विचार यह है: यदि आपके पास एक आक्रामक पूर्ण खोज है, तो इसे उस FULLTEXT initializationचरण के दौरान कम से कम डेटा इकट्ठा करें , इस प्रकार समय को कम करें।

मैंने पहले भी कई बार इसकी सिफारिश की है

शुक्रिया # 2

कृपया सुनिश्चित करें कि आप InnoDB- आधारित पूर्ण विकल्प सेट कर रहे हैं, MyISAM के लिए नहीं। आपके द्वारा संबंधित दो विकल्प होने चाहिए

एक पल के लिए इसके बारे में सोचो। पाठ क्षेत्र VARCHAR (600) है। कहते हैं कि औसत 300 बाइट्स है। आपके पास उनमें से 29,000,000 मिलियन हैं। ऐसा होगा कि 8GB का एक छोटा सा होगा। शायद बढ़ती innodb_ft_cache_size और innodb_ft_total_cache_size भी मदद कर सकती हैं।

सुनिश्चित करें कि आपके पास बड़े InnoDB FULLTEXT बफ़र्स के लिए पर्याप्त RAM है।

कोशिश तो करो !!!


दोनों सुझावों की कोशिश की, इसने लगभग 10 सेकंड का समय 200 सेकंड तक ला दिया। अजीब बात है कि बफर पूल केवल 9% उपयोग पर है ...
hichris123

AGAINST भाग के अंदर एक प्लस चिह्न लगाने का प्रयास करें: SELECT B.* FROM (SELECT id FROM socomments WHERE MATCH (Text) AGAINST ('+"fixed the post"' IN BOOLEAN MODE)) A LEFT JOIN socomments B USING (id);और देखें कि क्या इससे कोई फर्क पड़ता है।
RolandoMySQLDBA

कारण मैंने प्लस साइन का सुझाव दिया है? Doc ( dev.mysql.com/doc/refman/5.6/en/fulltext-boolean.html ) का कहना है कि A leading or trailing plus sign indicates that this word must be present in each row that is returned. InnoDB only supports leading plus signs.आपके विशेष मामले में, सटीक वाक्यांश fixed the postमौजूद होना चाहिए।
RolandoMySQLDBA

समान परिणाम। थोड़ा तेज़ और धीमा, इसलिए शायद सिर्फ मिनट के अंतर के कारण जब इसे निष्पादित किया गया था।
hichris123

5

यदि आप InnoDB FULLTEXT इंडेक्स का उपयोग कर रहे हैं, तो क्वेरी अक्सर "FULLTEXT आरंभीकरण" स्थिति में लटकाएगी यदि आप एक तालिका के खिलाफ क्वेरी कर रहे हैं जिसमें बड़ी संख्या में हटाए गए पंक्तियां हैं। InnoDB के पूर्ण कार्यान्वयन में, हटाए गए पंक्तियों को तब तक छंटा नहीं जाता है जब तक कि बाद में ऑप्टिमाइज़ ऑपरेशन प्रभावित तालिका के विरुद्ध नहीं चलाया जाता है। देखें: https://dev.mysql.com/doc/refman/5.6/en/innodb-fulltext-index.html

हटाए गए रिकॉर्ड के लिए पूर्ण-पाठ अनुक्रमणिका प्रविष्टियों को निकालने के लिए, आपको पूर्ण-पाठ अनुक्रमणिका के पुनर्निर्माण के लिए innodb_optimize_fulltext_only = ON के साथ अनुक्रमित तालिका पर OPTIMIZE TABLE चलाना होगा।

कोई भी हटाए गए लेकिन शुद्ध किए गए रिकॉर्ड्स की जानकारी का निरीक्षण करके जानकारी_schema.innodb_ft_deleted को रिकॉर्ड नहीं कर सकता है

इसे हल करने के लिए, व्यक्ति को नियमित रूप से InnoDB FULLTEXT इंडेक्स वाली तालिकाओं के खिलाफ OPTIMIZE TABLE चलाना चाहिए।


मुझे इस पर तर्क मिलता है, लेकिन क्या आप इसे सत्यापित कर सकते हैं innodb_optimize_fulltext_only=1और एक OPTIMIZEमेज वास्तव में "प्रतीक्षा में" हटाए गए पंक्तियों का ध्यान रखती है? dba.stackexchange.com/questions/174486/…
Riedsio

1

MySQL में एक पुष्टिकृत बग है ( हटाए गए DOCID को InnoDB FULLTEXT टेबलों के OPTIMIZE के दौरान नहीं रखा गया है ) जो भारी डिलीट लोड (खरोंच से तालिका के पुनर्निर्माण के बिना) के तहत टैंक का प्रदर्शन करते हैं।

संबंधित


0

MySQL में फुल-टेक्स्ट इंडेक्स को बड़ी मात्रा में डेटा का समर्थन करने के लिए डिज़ाइन नहीं किया गया है, इसलिए जैसे ही आपका डेटासेट बढ़ रहा है, खोज की गति बहुत तेज़ी से नीचे गिर रही है। समाधानों में से एक सोलर या स्फिंक्स जैसे बाहरी पूर्ण-पाठ खोज इंजनों का उपयोग करना है, जिसने खोज कार्यक्षमता (प्रासंगिकता ट्यूनिंग और वाक्यांश खोज समर्थन, अंतर्निहित पहलुओं, स्निपेट्स, आदि) में सुधार किया है, जो क्वेरी सिंटैक्स और मध्य-गति तक बहुत तेज़ गति से बढ़ा है। डेटा सेट बढ़ाएँ।

सोलर जावा प्लेटफ़ॉर्म पर आधारित है, इसलिए यदि आप जावा-आधारित एप्लिकेशन चलाते हैं तो यह आपके लिए स्वाभाविक पसंद होगा, स्फिंक्स सी ++ पर लिखा गया है और MySQL के रूप में उसी तरह एक डेमन के रूप में काम कर रहा है। जैसे ही आप बाहरी इंजन को उस डेटा के साथ फीड करते हैं, जिसे आप खोजना चाहते हैं, आप MySQL से कुछ प्रश्नों को भी स्थानांतरित कर सकते हैं। मैं आपको नहीं बता सकता कि आपके मामले में कौन सा इंजन बेहतर है, मैं ज्यादातर Sphinx का उपयोग करता हूं और यहां उपयोग का उदाहरण है: http://astellar.com/2011/12/replacing-mysql-full-text-search-with-sphinx

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.