2009-10-24 4 views
3

인덱스를 사용하여 결과를 찾지 못했을 때 MySQL이 전체 테이블 스캔을 수행하지 못하도록하는 방법이 있습니까? 예를 들어MySQL이 쿼리에서 전체 테이블 스캔을 사용하지 못하도록

이 쿼리 : X는 조건이 테이블의 데이터에 의해 만족 될 수없는 경우, 전체 검사 것 조건을 만족 및 행이 반환 적어도 1가 있지만, 경우

SELECT * 
FROM a 
WHERE (X BETWEEN a.B AND a.C) 
ORDER BY a.B DESC 
LIMIT 1; 

는 효율적인가요 매우 비쌀 수 있습니다.

이 특정 쿼리를 최적화하고 싶지는 않습니다. 단지 예일뿐입니다.

이 범위에서 X이 쿼리 나 외부에 EXPLAIN :

id select_type table type possible_keys key key_len ref rows filtered Extra 
1 SIMPLE a range long_ip long_ip 8 \N 116183 100.00 Using where 

상태 변수가 더 나은 정보를 표시합니다.

Handler_read_prev 84181 
Key_read_requests 11047 

범위 : 범위의 X의 외부에 대한

Handler_read_key 1 
Key_read_requests 12 

오직 지난 1

UPDATE 성장에서 Handler_read_prev을 방지 할 수있는 방법이 있었다면. 정말 내 질문에 대답하지 않기 때문에 직접 대답을 받아 들일 수 없습니다 (HANDLER는 훌륭한 기능입니다). MySQL이 전체 검사를하지 못하도록하는 일반적인 방법은 없다고 생각됩니다. key = 'X'와 같은 단순한 조건은 "불가능한 곳"으로 간주되지만, BETWEEN과 같은 더 복잡한 것들은 그렇지 않습니다.

+0

색인 (B, C)이 있다고 가정하고 개별적으로 각 열이 아닌 것으로 가정합니다. 어쩌면 인덱스 통계가 잘못되었을 수도 있습니다. 테이블에서'ANALYZE'를 실행하려고 시도 했습니까? –

+0

예,하지만 "인덱스 통계가 잘못되었습니다"라는 것은 무엇을 의미합니까? 나는이 쿼리를 최적화하려고하지 않고있다. MySQL이 전체 테이블 스캔을 수행하는 것을 막을 수있는 방법이 있는지 묻는 것이다. –

+0

쿼리 최적화 프로그램은 데이터 통계를 사용합니다. 통계를 기반으로 비용을 결정하고 가장 적합한 방법을 선택합니다. 통계가 꺼져 있으면 비용 견적이 틀리며 데이터를 얻는 데 가장 좋은 방법을 사용하지 않습니다. 나는 새로 작성된 인덱스가있는 큰 테이블에서 쿼리가 결과를 반환하지 않더라도 인덱스를 사용하기 때문에 이렇게 말하고 있습니다. –

답변

0

내가 결국 해낸 것입니다 :

HANDLER a OPEN; 
HANDLER a READ BC <= (X); 
HANDLER a CLOSE; 

BC 키의 이름 (B, C)입니다. 우리 B DESC하여 테이블을 주문할 경우, 결과가 X 테이블 (A)의 범위 내에없는 경우는 지금

SELECT * 
FROM a 
WHERE (X BETWEEN a.B AND a.C) 
ORDER BY a.B DESC 
LIMIT 1; 

동일하게 guranteed되어, 방금의 AC X보다 큰 것을 확인할 수있다, 그렇지 않은 경우 X가 범위를 벗어 났으므로 더 이상 볼 필요가 없습니다.

매우 우아하지는 않지만 삽입 또는 업데이트 할 때마다 테이블을 사용해야합니다.

1

인덱스에서 사용할 수있는 데이터 만 사용하는 "완전 덮음"하위 쿼리를 작성할 수 있습니다. 리턴 된 기본 키에 따라 마스터 테이블에서 행을 찾을 수 있습니다.

다음 질의가 완전히 (ID) (B, ID) 및 (C, ID)의 인덱스에 의해 덮여

:

select * 
from a 
where id in (
    select id 
    from a 
    where x <= C 
    and id in (
     select id 
     from a 
     where B <= X 
    ) 
) 
limit 1 

각 SELECT 하나의 인덱스를 사용하여 (B상의 최 인덱스 ,신분증); 가운데 SELECT는 (C, id)에 인덱스를 사용하고 외부 SELECT는 기본 키를 사용합니다. 여기

+1

LIMIT 및 IN은 지원되지 않습니다.이 쿼리 외에도 속도가 매우 느릴 수 있으며 쿼리가 인덱스에 포함되지 않는 것을 확인할 수 없습니다. 실제로, MySQL이 인덱스에서 응답을 찾지 못했을 때 MySQL을 중지하는 방법이 문제였습니다 (처음에해야 할 일입니다). –

+0

하위 쿼리에서 한도를 지정하고 바깥 쿼리로 이동했습니다. 중간 제안이 비어 있기 때문에 제안 된 쿼리는 결과를 찾을 수 없을 때 테이블 스캔을 수행하지 않습니다. 꽤 빠르 네요, 시도해 보셨습니까? – Andomar

+0

예. 10mb 테이블에서 1 초 이상 실행됩니다. 2 개의 내부 쿼리는 수천 개의 행을 반환합니다. –

관련 문제