ฉันมีสองตารางตารางแรกประกอบด้วยบทความ / บล็อกโพสต์ทั้งหมดภายใน CMS บทความเหล่านี้บางส่วนอาจปรากฏในนิตยสารซึ่งในกรณีนี้พวกเขามีความสัมพันธ์กับต่างประเทศที่สำคัญกับตารางอื่นที่มีข้อมูลเฉพาะของนิตยสาร
นี่คือเวอร์ชันที่เรียบง่ายของไวยากรณ์การสร้างตารางสำหรับสองตารางเหล่านี้ที่มีแถวที่ไม่จำเป็นออกมา:
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 บทความและฉันได้เขียนสคริปต์ Pythonแบบง่ายที่สามารถใช้เพื่อเติมฐานข้อมูลทดสอบด้วยข้อมูลตัวอย่างหากพวกเขาต้องการทำซ้ำปัญหานี้ในเครื่อง
ถ้าฉันเลือกจากหนึ่งในตารางเหล่านี้ 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 |
+----+-------------+--------------+--------+-----------------------------------+---------+---------+----------------------------------------+-------+----------+---------------------------------+
- แก้ไขวันที่ 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
อาจไม่เป็นดัชนีที่ดีที่สุดที่จะใช้อีกต่อไป
ใครบ้างที่สามารถแนะนำกลยุทธ์ในการปรับปรุงประสิทธิภาพสำหรับการค้นหานี้
base_article_is_published
(is_published
) .. ดูเหมือนผมมันเป็นชนิดบูลีน ..