अन्य तालिका में शामिल होने पर MySQL अनुक्रमित का उपयोग नहीं कर रहा है


11

मेरे पास दो टेबल हैं, पहली तालिका में सीएमएस के भीतर सभी लेख / ब्लॉग पोस्ट हैं। इनमें से कुछ लेख एक पत्रिका में भी दिखाई दे सकते हैं, जिस स्थिति में उनके पास एक अन्य तालिका के साथ एक विदेशी कुंजी संबंध होता है जिसमें पत्रिका विशिष्ट जानकारी होती है।

यहाँ कुछ गैर-आवश्यक पंक्तियों के साथ इन दो तालिकाओं के लिए तालिका सारणी बनाने का एक सरल संस्करण है:

CREATE TABLE `base_article` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `date_published` datetime DEFAULT NULL,
  `title` varchar(255) NOT NULL,
  `description` text,
  `content` longtext,
  `is_published` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `base_article_date_published` (`date_published`),
  KEY `base_article_is_published` (`is_published`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE `mag_article` (
    `basearticle_ptr_id` int(11) NOT NULL,
    `issue_slug` varchar(8) DEFAULT NULL,
    `rubric` varchar(75) DEFAULT NULL,
    PRIMARY KEY (`basearticle_ptr_id`),
    KEY `mag_article_issue_slug` (`issue_slug`),
    CONSTRAINT `basearticle_ptr_id_refs_id` FOREIGN KEY (`basearticle_ptr_id`) REFERENCES `base_article` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CMS में कुल मिलाकर लगभग 250,000 लेख हैं और मैंने एक साधारण पायथन स्क्रिप्ट लिखी है जिसका उपयोग नमूना डेटा के साथ एक परीक्षण डेटाबेस को पॉप्युलेट करने के लिए किया जा सकता है यदि वे इस मुद्दे को स्थानीय रूप से दोहराना चाहते हैं।

यदि मैं इन तालिकाओं में से किसी एक का चयन करता हूं, तो MySQL को उचित सूचकांक चुनने या लेखों को जल्दी से पुनर्प्राप्त करने में कोई समस्या नहीं है। हालाँकि, जब दो टेबल एक साथ एक साधारण क्वेरी में शामिल हो जाते हैं जैसे:

SELECT * FROM `base_article` 
INNER JOIN `mag_article` ON (`mag_article`.`basearticle_ptr_id` = `base_article`.`id`)
WHERE is_published = 1
ORDER BY `base_article`.`date_published` DESC
LIMIT 30

MySQL एक उपयुक्त क्वेरी और प्रदर्शन प्लमसेट लेने में विफल रहता है। यहां प्रासंगिक व्याख्या को विस्तारित किया गया है (जिसके लिए निष्पादन समय एक सेकंड से अधिक है):

+----+-------------+--------------+--------+-----------------------------------+---------+---------+----------------------------------------+-------+----------+---------------------------------+
| id | select_type |    table     |  type  |           possible_keys           |   key   | key_len |                  ref                   | rows  | filtered |              Extra              |
+----+-------------+--------------+--------+-----------------------------------+---------+---------+----------------------------------------+-------+----------+---------------------------------+
|  1 | SIMPLE      | mag_article  | ALL    | PRIMARY                           | NULL    | NULL    | NULL                                   | 23830 | 100.00   | Using temporary; Using filesort |
|  1 | SIMPLE      | base_article | eq_ref | PRIMARY,base_article_is_published | PRIMARY | 4       | my_test.mag_article.basearticle_ptr_id |     1 | 100.00   | Using where                     |
+----+-------------+--------------+--------+-----------------------------------+---------+---------+----------------------------------------+-------+----------+---------------------------------+
  • EDIT SEPT 30: मैं WHEREइस क्वेरी से क्लॉज़ हटा सकता हूं , लेकिन फिर EXPLAINभी वही दिखता है और क्वेरी अभी भी धीमी है।

एक संभावित समाधान एक सूचकांक को मजबूर करना है। FORCE INDEX (base_articel_date_published)लगभग 1.6 मिलीसेकंड में निष्पादित क्वेरी में परिणामों के साथ एक ही क्वेरी चला रहा है ।

+----+-------------+--------------+--------+---------------+-----------------------------+---------+-------------------------+------+-----------+-------------+
| id | select_type |    table     |  type  | possible_keys |             key             | key_len |           ref           | rows | filtered  |    Extra    |
+----+-------------+--------------+--------+---------------+-----------------------------+---------+-------------------------+------+-----------+-------------+
|  1 | SIMPLE      | base_article | index  | NULL          | base_article_date_published |       9 | NULL                    |   30 | 833396.69 | Using where |
|  1 | SIMPLE      | mag_article  | eq_ref | PRIMARY       | PRIMARY                     |       4 | my_test.base_article.id |    1 | 100.00    |             |
+----+-------------+--------------+--------+---------------+-----------------------------+---------+-------------------------+------+-----------+-------------+

मैं इस क्वेरी पर एक सूचकांक को बाध्य करने के लिए नहीं करना पसंद करूंगा यदि मैं इसे कई कारणों से टाल सकता हूं। सबसे विशेष रूप से, इस मूल क्वेरी को विभिन्न तरीकों से फ़िल्टर किया जा सकता है / संशोधित किया जा सकता है (जैसे कि फ़िल्टर करना issue_slug) जिसके बाद base_article_date_publishedअब उपयोग करने के लिए सबसे अच्छा सूचकांक नहीं हो सकता है।

क्या कोई इस क्वेरी के लिए प्रदर्शन में सुधार के लिए कोई रणनीति सुझा सकता है?


यदि कॉलम "is_published" केवल दो या तीन मान रखता है, तो आप वास्तव में उस इंडेक्स कुंजी को छोड़ सकते हैं base_article_is_published( is_published) .. मुझे लगता है कि यह एक बुलियन प्रकार है ..
रेमंड निजलैंड

उत्तर को संपादित किया
रेमंड निजलैंड

जवाबों:


5

इस बारे में क्या करना चाहिए "अस्थायी का उपयोग करना; फाइलशॉर्ट का उपयोग करना" की आवश्यकता को दूर करना चाहिए क्योंकि डेटा पहले से ही सही प्रकार में है।

आपको उस चाल को जानने की आवश्यकता है कि MySQL को "अस्थायी का उपयोग करना; फाइलशॉर्ट का उपयोग करना" की आवश्यकता क्यों है।

आवश्यकता को दूर करने के बारे में व्याख्या के लिए दूसरा चक्रफल देखें

SELECT
      *
    FROM base_article

    STRAIGHT_JOIN 
      mag_article
    ON
      (mag_article.basearticle_ptr_id = base_article.id)

    WHERE
      base_article.is_published = 1

    ORDER BY
      base_article.date_published DESC

देख http://sqlfiddle.com/#!2/302710/2

बहुत अच्छा काम करता है मुझे इसकी आवश्यकता है कुछ समय पहले देश / शहर की तालिकाओं के लिए यहाँ उदाहरण देखें http://sqlfiddle.com/#!2/b34870/41

संपादित करें आप भी इस उत्तर का विश्लेषण करना चाह सकते हैं यदि base_article.is_published = 1 हमेशा 1 रिकॉर्ड देता है जैसे कि आपका विवरण समझाया गया है कि INNER JOIN डिलीट टेबल नीचे दिए गए उत्तर में प्रश्नों की तरह बेहतर प्रदर्शन दे सकती है।

/programming/18738483/mysql-slow-query-using-filesort/18774937#18774937


जीवन रक्षक उत्तर! मैं JOINकेवल उपयोग कर रहा था, लेकिन MySQL सूचकांक नहीं उठा रहा था । बहुत बहुत धन्यवाद रेमंड
मैक्सिमस

4

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

SELECT * FROM
(SELECT * FROM base_article
WHERE is_published = 1
ORDER BY date_published LIMIT 30) A
INNER JOIN mag_article B
ON A.id = B.basearticle_ptr_id;

या

SELECT B.*,C.* FROM
(SELECT id FROM base_article
WHERE is_published = 1
ORDER BY date_published LIMIT 30) A
LEFT JOIN base_article ON A.id = B.id
LEFT JOIN mag_article C ON B.id = C.basearticle_ptr_id;

अपने विचारों को संशोधित करें

ALTER TABLE base_article DROP INDEX base_article_is_published;
ALTER TABLE base_article ADD INDEX ispub_datepub_index (is_published,date_published);

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


प्रतिक्षेपक: काम नहीं कर रहा हूँ मुझे डर है, क्योंकि LIMIT 30उपश्रम में है (उन 30 पंक्तियों में से सभी mag_articlesतालिका में नहीं होंगे)। अगर मैं LIMITबाहरी क्वेरी पर जाता हूं तो प्रदर्शन मेरे मूल के समान है। अनुक्रमित संशोधित करें: MySQL उस सूचकांक का उपयोग नहीं करता है। WHEREमेरी मूल क्वेरी से क्लॉज़ हटाने से कोई फ़र्क नहीं पड़ता।
जोशमेकर

दूसरी रिफ्लेक्टर विधि ने अविश्वसनीय रूप से अच्छा काम किया, मेरी तालिका में क्वेरी समय नाटकीय रूप से 8 सेकंड से 0.3 सेकंड तक कम कर दिया गया है ... धन्यवाद सर !!
andreszs
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.