मैं इस क्वेरी अनुकूलन करने के लिए कोशिश कर रहा हूँ:Mysql धीमी क्वेरी: इनर + जुड़ने के द्वारा कारणों filesort
SELECT `posts`.* FROM `posts` INNER JOIN `posts_tags` ON `posts`.id = `posts_tags`.post_id WHERE (((`posts_tags`.tag_id = 1))) ORDER BY posts.created_at DESC;
टेबल के आकार 38k पंक्तियाँ, और 31k है और mysql "filesort" का उपयोग करता है तो यह बहुत हो जाता है धीमी गति से। मैंने अलग-अलग इंडेक्स का उपयोग करने की कोशिश की, कोई भाग्य नहीं।
CREATE TABLE `posts` ( `id` int(11) NOT NULL auto_increment, `created_at` datetime default NULL, PRIMARY KEY (`id`), KEY `index_posts_on_created_at` (`created_at`), KEY `for_tags` (`trashed`,`published`,`clan_private`,`created_at`) ) ENGINE=InnoDB AUTO_INCREMENT=44390 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci CREATE TABLE `posts_tags` ( `id` int(11) NOT NULL auto_increment, `post_id` int(11) default NULL, `tag_id` int(11) default NULL, `created_at` datetime default NULL, `updated_at` datetime default NULL, PRIMARY KEY (`id`), KEY `index_posts_tags_on_post_id_and_tag_id` (`post_id`,`tag_id`) ) ENGINE=InnoDB AUTO_INCREMENT=63175 DEFAULT CHARSET=utf8
+----+-------------+------------+--------+--------------------------+--------------------------+---------+---------------------+-------+-----------------------------------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+------------+--------+--------------------------+--------------------------+---------+---------------------+-------+-----------------------------------------------------------+ | 1 | SIMPLE | posts_tags | index | index_post_id_and_tag_id | index_post_id_and_tag_id | 10 | NULL | 24159 | Using where; Using index; Using temporary; Using filesort | | 1 | SIMPLE | posts | eq_ref | PRIMARY | PRIMARY | 4 | .posts_tags.post_id | 1 | | +----+-------------+------------+--------+--------------------------+--------------------------+---------+---------------------+-------+-----------------------------------------------------------+ 2 rows in set (0.00 sec)
सूचकांक मैं filesort का उपयोग कर mysql से बचने के लिए परिभाषित करने की जरूरत किस तरह का? क्या यह संभव है जब ऑर्डर फ़ील्ड क्लॉज में न हो?
अद्यतन: रूपरेखा परिणाम:
mysql> show profile for query 1; +--------------------------------+----------+ | Status | Duration | +--------------------------------+----------+ | starting | 0.000027 | | checking query cache for query | 0.037953 | | Opening tables | 0.000028 | | System lock | 0.010382 | | Table lock | 0.023894 | | init | 0.000057 | | optimizing | 0.010030 | | statistics | 0.000026 | | preparing | 0.000018 | | Creating tmp table | 0.128619 | | executing | 0.000008 | | Copying to tmp table | 1.819463 | | Sorting result | 0.001092 | | Sending data | 0.004239 | | end | 0.000012 | | removing tmp table | 0.000885 | | end | 0.000006 | | end | 0.000005 | | query end | 0.000006 | | storing result in query cache | 0.000005 | | freeing items | 0.000021 | | closing tables | 0.000013 | | logging slow query | 0.000004 | | cleaning up | 0.000006 | +--------------------------------+----------+
Update2:
रियल क्वेरी (कुछ और बूलियन क्षेत्रों, अधिक बेकार अनुक्रमित)
SELECT `posts`.* FROM `posts` INNER JOIN `posts_tags` ON `posts`.id = `posts_tags`.post_id WHERE ((`posts_tags`.tag_id = 7971)) AND (((posts.trashed = 0) AND (`posts`.`published` = 1 AND `posts`.`clan_private` = 0)) AND ((`posts_tags`.tag_id = 7971))) ORDER BY created_at DESC LIMIT 0, 10;
खाली सेट (1.25 सेकंड)
साथ बाहर आदेश - 0.01s।
+----+-------------+------------+--------+-----------------------------------------+-----------------------+---------+---------------------+-------+--------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+------------+--------+-----------------------------------------+-----------------------+---------+---------------------+-------+--------------------------+ | 1 | SIMPLE | posts_tags | index | index_posts_tags_on_post_id_and_tag_id | index_posts_tags_... | 10 | NULL | 23988 | Using where; Using index | | 1 | SIMPLE | posts | eq_ref | PRIMARY,index_posts_on_trashed_and_crea | PRIMARY | 4 | .posts_tags.post_id | 1 | Using where | +----+-------------+------------+--------+-----------------------------------------+-----------------------+---------+---------------------+-------+--------------------------+
समाधान
- क्वेरी (ऐप्लिकेशन कोड में दो छोटे परिवर्तन) "posts_tags.created_at DESC द्वारा आदेश" के लिए अद्यतन
- सूचकांक कहा: index_posts_tags_on_created_at।
यह सब कुछ है!
धन्यवाद के साथ filesort का उपयोग करता है! मैं छँटाई (पता करने के लिए टैग निर्माण तिथि की कोई जरूरत नहीं) के लिए posts_tags.created_at उपयोग करने के लिए क्वेरी अद्यतन और index_posts_tags_on_created_at ... कोई और अधिक filesort जोड़ा गया! :) – Alexander
क्या क्वेरी प्लानर को सूचित करना संभव है कि अलग-अलग तालिकाओं में दो कॉलम समान हैं, इसलिए आपको स्पष्ट रूप से निर्दिष्ट नहीं करना होगा कि इसे post.created_at के बजाय post_tags.created_at का उपयोग करना चाहिए? – sorenbs