2012-04-13 5 views
2

this wiki article을 읽고 MySQL 데이터베이스의 인덱싱 된 열과 함께 IN() 절을 사용하면 SELECT 성능이 저하된다는 것을 알았습니다. 내 질문은 어떻게 그것의 기능을 유지하면서 어떤 IN() 절을 사용하지 않습니다 내 쿼리를 다시 작성할 수 있습니다?IN() 절을 사용하여 쿼리 최적화

내 쿼리는 다음과 같습니다

SELECT 
    `Route`.`route_id`, `Route`.`order`, `Route2`.`order` 
FROM 
    `routes` AS `Route` 
INNER JOIN 
    `routes` AS `Route2` 
ON `Route`.`route_id` = `Route2`.`route_id` 
WHERE 
    `Route`.`station_line_id` IN ([10 values]) AND 
    `Route2`.`station_line_id` IN ([10 values]) AND 
    `Route`.`order` <= `Route2`.`order` 
GROUP BY ` 
    `Route`.`station_line_id`, `Route2`.`station_line_id`, (`Route2`.`order` - `Route`.`order`) 

내가 (route_id, station_line_id, station_id 및 line_id), ID 열에는 기본 키 인 상태 (테이블 그냥 읽기 전용 한 번 생성 된 모든 열을 색인을, 그래서 모든 것에 대한 색인 작성에 대한 걱정은 없습니다.) IN() 절의 [10 values]은 쉼표로 구분됩니다 (예 : IN(1, 2, ..., 10)).

기본적으로 테이블 경로 테이블을 자체 조인하고 결과를 그룹화하여 원하는 레코드를 얻습니다. 다른 조인은 연관된 데이터를 검색하는 데 사용됩니다.

InnoDB 스토리지 엔진을 사용하여 성능 측면에서 30 초 이상 비슷한 쿼리를 실행합니다. MyISAM을 사용하면 5 초를 넘습니다. 그러나 나는 결과가 더 빨리 추출 될 수 있다고 믿습니다. 테이블에 450 만 개의 레코드가 있습니다.

+0

검색어를 조금 포맷하는 데주의해야합니까? –

+0

내 질문을 수정했습니다. 죄송합니다. – linkyndy

+0

IN (1,3,47, ... 89) 또는 'IN (SELECT column FROM table)'과 같은 10 개의 값이 있습니까? –

답변

1

'해시 색인'을 사용하면 다음과 같은 쿼리에서 최상의 성능을 얻을 수 있습니다. '표준'색인은 log (n) 시간에 항목을 조회 할 수있는 B + 트리입니다. 여기서 n은 표의 행 수입니다. 그들은 또한 정렬 된 순서를 유지하므로 ... WHERE station_line_id > 14과 같은 쿼리를 효율적으로 수행 할 수 있으므로 Order 열에서 사용하려는 쿼리를 효율적으로 처리 할 수 ​​있습니다.

그러나 귀하의 경우 IN 절을 사용하면 동등한 것을 찾을 수 있습니다. 이 경우 B + 트리는 "[10 값]"을 모두 m 개 조회해야하기 때문에 m * log (n) 시간이 걸리므로 5 ~ 30 초가 걸립니다.

해시 인덱스는 테이블의 행 수에 (이론적으로) 의존하지 않는 일정한 시간 (매우 빠름)으로 동일한 항목을 조회하는 데 사용됩니다. 테이블. 해시 색인의 단점은 < 또는 >과 같은 검색어를 사용할 수 없지만 IN 절에서 수행중인 것과 같은 동등성 검색어가 가장 빠른 것입니다 (station_line_id).

편집 : 특히 MySQL의 경우, 불행히도 널리 사용되는 데이터베이스 엔진에서 HASH 인덱스를 지원하지 않습니다. MEMORY 또는 HEAP 엔진을 사용할 수 있다면 HASH 인덱스를 사용할 수 있습니다. 메모리에있는 모든 것이 어쨌든 성능을 상당히 향상시킬 수 있습니다. 그럴 가치가있어.

+0

현재 공유 호스트에 있으며 메모리에 이러한 양의 데이터를 저장하는 것이 옵션이 아닌 것으로 생각됩니다 (또는?). – linkyndy

+1

MyISAM과 InnoDB에는 해시 인덱스가 없습니다. –

+0

데이터 구조에 따라 여전히 가치가있을 수 있습니다. 2.7GB의 데이터와 1.1GB의 색인에 맞는 4 천 5 백만 행의 표가 있습니다. 이 속도로 표는 약 .27 + .11 GB <= 400MB의 메모리를 차지합니다. 나는 당신의 서버 요구 사항이 무엇인지 모르지만, 512MB는 VPS가 가지고있는 비합리적인 메모리가 아니다. 그게 당신을위한 옵션인지는 모르겠지만 성능 향상을 보장 할 수 있습니다. –