문제

다음과 같이 보이는 쿼리가 있습니다.

select
id
, int1
, int2
, (select count(*) from big_table_with_millions_of_rows 
    where id between t.int1 and t.int2)
from myTable t
where
....

이 선택은 정확히 하나의 행을 반환합니다. 인라인 선택에 사용 된 ID는 인덱스 된 열 (기본 키)입니다. 내가 교체하면 t.int1 그리고 t.int2 이 단일 행에 의해 int1/int2의 값이 반환되면 쿼리는 밀리 초로 완료됩니다. int1/int2에 대한 참조와 함께 위와 같이 쿼리를 실행하면 약 10 분이 걸립니다. 프로파일 러를 실행하고 실제로 발생하는 일을 살펴보면 엔진이 인라인 쿼리에서 데이터를 반환하는 데 바쁘다는 것을 알 수 있습니다. MySQL이 실제로 실행되는 것처럼 보입니다

select ... from big_table_with_millions_of_rows 

적용하기 전에 인라인 쿼리의 비트

where id between t.int1 and t.int2

결과에 비트. 이것이 사실 일 수 있습니까? 그렇지 않다면, 무슨 일이 일어나고 있습니까? 나는 항상 인라인이라고 생각했다 SELECTs는 쿼리의 마지막 요소로 행으로 실행되기 때문에 잠재적으로 위험했지만 이와 같은 상황에 대해 SELECT 실제로 매우 선택적이며 매우 효율적 일 수 있습니다. 누구든지 이것에 대해 어떤 빛을 흘릴 수 있습니까?

편집하다: 지금까지 피드백에 감사드립니다. 내 우려는 인라인 쿼리의 행 별 특성에 관한 것이 아니라 (동일 한) 하드 코딩 된 값이 아닌 변수에 직면 할 때 기본 키 인덱스를 사용할 수 없다는 사실에 관한 것이 아닙니다. 내 생각에 분석이 최근에 실행되지 않았다면 Optimizer는 데이터 배포에 대한 지식이 없기 때문에 테이블 스캔을 수행해야한다고 가정합니다. 그러나 기본 키에서 범위 조회가 수행된다는 사실이이를 보상하지 않아야합니까?

도움이 되었습니까?

해결책

상관 관계 서브 쿼리가 잘 최적화되지 않으면이 쿼리를 시도하십시오.

select
  t.id
, t.int1
, t.int2
, count(*)
from myTable t
left outer join big_table_with_millions_of_rows b
  on (b.id between t.int1 and t.int2)
where
....
group by t.id

훨씬 더 나은 최적화해야합니다.


RE 귀하의 업데이트 된 질문 : 맞습니다. MySQL은 최적화 측면에서 시장에서 가장 정교한 RDBM이 아닙니다. MySQL이 이와 같은 코너 케이스를 최적화 할 수 없을 때 놀라지 마십시오.

나는 사용 편의성과 오픈 소스 및 모든 좋은 것들에 대한 MySQL의 팬이지만 진실은 경쟁사가 기술 측면에서 MySQL보다 훨씬 앞서 있다는 것입니다. 모든 RDBM에는 "사각 지대"가 있지만 MySQL은 더 큰 것 같습니다.

또한 최신 버전의 MySQL을 사용하고 있는지 확인하십시오. 릴리스마다 최적화를 개선하므로 최신 버전으로 더 나은 결과를 얻을 수 있습니다.

다른 팁

가능한 경우 Join을 사용하여 상관 된 하위 쿼리를 피하십시오.

MySQL 성능에 대한이 훌륭한 비디오를보십시오 YouTube. 스피커 Jay Pipes는 31:00 분으로 가십시오.

서브 쿼리가 포함 된 쿼리에서 필드를 참조하는 경우, 참조 된 필드가 각 행마다 다를 수 있으므로 포함 된 쿼리의 모든 행 당 하위 쿼리를 다시 실행해야합니다. 완전히 독립적 인 경우 외부 쿼리가 처리되기 전에 한 번에 실행할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top