MySQL 및 인라인 선택이 선택됩니다
문제
다음과 같이 보이는 쿼리가 있습니다.
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
결과에 비트. 이것이 사실 일 수 있습니까? 그렇지 않다면, 무슨 일이 일어나고 있습니까? 나는 항상 인라인이라고 생각했다 SELECT
s는 쿼리의 마지막 요소로 행으로 실행되기 때문에 잠재적으로 위험했지만 이와 같은 상황에 대해 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 분으로 가십시오.
서브 쿼리가 포함 된 쿼리에서 필드를 참조하는 경우, 참조 된 필드가 각 행마다 다를 수 있으므로 포함 된 쿼리의 모든 행 당 하위 쿼리를 다시 실행해야합니다. 완전히 독립적 인 경우 외부 쿼리가 처리되기 전에 한 번에 실행할 수 있습니다.