두 개의 테이블이 있는데 첫 번째 테이블에는 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이 적절한 쿼리 및 성능 저하를 선택하지 못했습니다. 관련 Explain 확장 (실행 시간이 1 초 이상임)은 다음과 같습니다.
+----+-------------+--------------+--------+-----------------------------------+---------+---------+----------------------------------------+-------+----------+---------------------------------+
| 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 |
+----+-------------+--------------+--------+-----------------------------------+---------+---------+----------------------------------------+-------+----------+---------------------------------+
- 편집 9 월 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
그것이 부울 타입이다 .. .. 나에게 보이는)