我有两个表,第一个表包含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总共包含约25万篇文章,并且我编写了一个简单的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
)..在我看来这是一个布尔类型..