크롤링 할 URI 목록을 저장하는 테이블이 있습니다. 이 'crawl_index'테이블 스키마는 다음과 같습니다이 테이블에 대한MySQL - "Group by"의 성능 문제
CREATE TABLE `crawl_index` (
`id` INTEGER(10) NOT NULL AUTO_INCREMENT,
`uri` TEXT NOT NULL,
`domain` VARCHAR(255) NOT NULL,
`last_crawled_date` INTEGER(10) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
INDEX `crawler_INDEX_1` (`domain`),
INDEX `crawler_INDEX_2` (`last_crawled_date`)
) ENGINE=InnoDB;
일부 세부 정보 :
이- 가 약 1M 행이 포함되어 있습니다.
- 거의 60 %의 행에 "last_crawled_date"가 0으로 설정되어 있습니다 (크롤링 된 페이지에서 실제로 페이지를 크롤링하는 것보다 URI를 추출하는 것이 빠릅니다).
- "id"필드는 사용되지 않습니다. 내가 바인딩되지 않은 텍스트이기 때문에 나는 "uri"필드에 기본 키를 만들 수 없으므로 명시적인 primary_key를 갖는 스키마에만 추가합니다.
- URI가 이미되어 나는 모든 반환을하지 않으려는
- 지난 2 일 내에 기어 안 : 내가 원하는 무엇
는 다음과 같은 제약 N 행을 선택하는 것입니다 동시에 동일한 도메인에서 너무 많은 요청을하지 않도록 동일한 도메인에서 오는 URI. 그것은 나에게 이런 종류의 결과 제공
select * from crawl_index where last_crawled_date <= 1373273029 group by domain limit 3;
:
+--------+------------------------+--------------+-------------------+ | id | uri | domain | last_crawled_date | +--------+------------------------+--------------+-------------------+ | 60239 | http://example1.com/1 | example1.com | 0 | | 239 | http://example2.com/1 | example2.com | 0 | | 120239 | http://example3.com/1 | example3.com | 0 | +--------+------------------------+--------------+-------------------+ 3 rows in set (1,23 sec)
그것은 작동을하지만은 않고 동일한 쿼리에 비해 매우 느린 순간
, 나는이 쿼리를 시도 "group by"성명서.
+----+-------------+-------------+-------+-----------------+-----------------+---------+------+-------+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------+-------+-----------------+-----------------+---------+------+------+------------------------+
| 1 | SIMPLE | crawl_index | range | crawler_INDEX_1 | crawler_INDEX_2 | 4 | NULL | 71588 | Using index condition |
| | | | | crawler_INDEX_2 | | | | | Using temporary |
| | | | | | | | | | Using filesort |
+----+-------------+-------------+-------+-----------------+-----------------+---------+------+-------+-----------------------+
이미 I : : 그 쿼리에 explain
를 실행하면,이 가지고
- 이 LAST_CRAWLED_DATE 및 도메인 필드에 인덱스를 만들
- 이 날짜 비교를 피하기 위해 내 LAST_CRAWLED_DATE를 저장하는 정수를 사용을
- 은 PHP 코드에서 max_date를 미리 계산하여 mysql이 나를 대신하도록 요구하지 않도록합니다.
이 쿼리를 향상시킬 수있는 아이디어가 있습니까? 사용
는
크롤링 할 새 도메인을 추가 할 때마다 스키마를 업데이트해야하므로 'ENUM'을 사용할 수 없습니다. 메모리 제한을 늘리는 것이 좋습니다.나는 그것을 시험해보고 그것이 퍼포먼스가 증가했는지를 말해 줄 것이다. 하지만 지금은, Im이 왜 "파일", "임시"및 "색인"을 더 이상 사용하지 않고 그냥 "어디에서"사용 하는지를 설명하는 suddently 이유를 이해하려고합니다. 단지 내가 변경 한 것은 생산 제한을 시뮬레이션하기 위해 내 테이블에 수십만 개의 uris가 있습니다. 응답 시간은 기본적으로 1.5 초에서 2 초 사이입니다. 이상한... – Remi