프로덕션 서버에서 정상적으로 작동하는 쿼리가 매우 느리게 시작되었습니다 (몇 시간 만에).간단한 SELECT mysql 쿼리가 매우 느림 (교차 사용)
이 그 것이다 :
SELECT * FROM news_articles WHERE published = '1' AND news_category_id = '4' ORDER BY date_edited DESC LIMIT 1;
이
이것은 EXPLAIN
의 출력 (~ 테이블 갖는다 200.000 행) 실행 (20-30) 초까지 취
+----+-------------+---------------+-------------+----------------------------+----------------------------+---------+------+------+--------------------------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------------+-------------+----------------------------+----------------------------+---------+------+------+--------------------------------------------------------------------------+
| 1 | SIMPLE | news_articles | index_merge | news_category_id,published | news_category_id,published | 5,5 | NULL | 8409 | Using intersect(news_category_id,published); Using where; Using filesort |
+----+-------------+---------------+-------------+----------------------------+----------------------------+---------+------+------+--------------------------------------------------------------------------+
놀아 보니 특정 색인 ()는 훨씬 더 빨리 만드는 :
는SELECT * FROM news_articles USE INDEX (date_edited) WHERE published = '1' AND news_category_id = '4' ORDER BY date_edited DESC LIMIT 1;
이 사람은을 실행하기 위해 밀리 초 걸립니다. 이 하나
EXPLAIN
출력은 다음과 같습니다
+----+-------------+---------------+-------+---------------+-------------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------------+-------+---------------+-------------+---------+------+------+-------------+
| 1 | SIMPLE | news_articles | index | NULL | date_edited | 8 | NULL | 1 | Using where |
+----+-------------+---------------+-------+---------------+-------------+---------+------+------+-------------+
열 news_category_id
, published
및 date_edited
모두 인덱싱됩니다.
스토리지 엔진은 InnoDB입니다.
CREATE TABLE `news_articles` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` text NOT NULL,
`subtitle` text NOT NULL,
`summary` text NOT NULL,
`keywords` varchar(500) DEFAULT NULL,
`body` mediumtext NOT NULL,
`source` varchar(255) DEFAULT NULL,
`source_visible` int(11) DEFAULT NULL,
`author_information` enum('none','name','signature') NOT NULL DEFAULT 'name',
`date_added` datetime NOT NULL,
`date_edited` datetime NOT NULL,
`views` int(11) DEFAULT '0',
`news_category_id` int(11) DEFAULT NULL,
`user_id` int(11) DEFAULT NULL,
`c_forwarded` int(11) DEFAULT '0',
`published` int(11) DEFAULT '0',
`deleted` int(11) DEFAULT '0',
`permalink` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
KEY `news_category_id` (`news_category_id`),
KEY `published` (`published`),
KEY `deleted` (`deleted`),
KEY `date_edited` (`date_edited`),
CONSTRAINT `news_articles_ibfk_3` FOREIGN KEY (`news_category_id`) REFERENCES `news_categories` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
CONSTRAINT `news_articles_ibfk_4` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=192588 DEFAULT CHARSET=utf8
나는 아마도 모두가 해당 인덱스를 사용하여 암시하는 않습니다 내 웹 응용 프로그램을 조회 변경할 수 있습니다 :
이
테이블 구조입니다. 그러나 이것은 상당한 연구입니다.MySQL을 조정하여 실제로 모든 쿼리를 다시 작성하지 않고 첫 번째 쿼리를보다 효율적으로 만들 수 있습니까? = 1 AND date_edited DESC의 LIMIT 1 BY news_category_id = 4 ORDER를 발표 news_articles로부터
SELECT *;
이 때 당신이 마지막으로 실행이'표 news_articles를 분석되었다'? 인덱스의 카디널리티를 업데이트해야 할 수도 있습니다. 또한 인덱스가 여러 필드에 걸쳐 있으면 성능이 향상 될 수 있습니다. – Wrikken
또한 거의 언제나'date_edited' 명령을 사용하면'ALTER TABLE news_articles ORDER BY date_edited;'가 무엇인지 알 수 있습니다 (전체 테이블을 다시 생성한다는 점에 유의하십시오. 따라서 약간의 시간이 소요될 수 있습니다. (아마도 날짜) – Wrikken
@Wrikken'ANALYZE'가 최근에 실행되었습니다. 여러 필드 인덱스 ('news_category_id','published','date_edited')를 사용 했었습니다. 나는 그것을 시험으로 떨어 뜨 렸지만 아무런 차이가 없었다. 나는 테이블이 이미 그 순서대로 정렬되어 있기 때문에 나를 위해 이해할 수있다. 행은 순서가 잘못되었을 수 있지만 대부분 edited_date에 의해 정렬됩니다) – vassilis