문제

약 100k 행의 다소 복잡한 쿼리가 있습니다.

쿼리는 SQL Server Express에서 13 초 안에 실행됩니다 (내 개발자 상자에서 실행)

동일한 인덱싱 및 테이블을 사용한 동일한 쿼리는 MySQL 5.1에서 실행하는 데 15 분 이상이 소요됩니다 (제작 상자에서 실행 - 훨씬 강력하고 100% 리소스로 테스트) 때때로 쿼리는 메모리가 잘못된 오류로 기계에 충돌합니다.

MySQL에서 무엇을 잘못하고 있습니까? 왜 그렇게 오래 걸립니까?

select e8.*
from table_a e8
inner join (
    select max(e6.id) as id, e6.category, e6.entity, e6.service_date
    from (
        select e4.* 
        from table_a e4
        inner join (
            select max(e2.id) as id, e3.rank, e2.entity, e2.provider_id, e2.service_date
            from table_a e2
            inner join (
                select min(e1.rank) as rank, e1.entity, e1.provider_id, e1.service_date
                from table_a e1
                where e1.site_id is not null
                group by e1.entity, e1.provider_id, e1.service_date 
            ) as e3
            on e2.rank= e3.rank
            and e2.entity = e3.entity
            and e2.provider_id = e3.provider_id
            and e2.service_date = e3.service_date
            and e2.rank= e3.rank
            group by e2.entity, e2.provider_id, e2.service_date, e3.rank
        ) e5
        on e4.id = e5.id
        and e4.rank= e5.rank                            
    ) e6
    group by e6.category, e6.entity, e6.service_date 
) e7
on e8.id = e7.id and e7.category = e8.category
도움이 되었습니까?

해결책

이 답변은 원래 삭제 된 질문에 게시하려고 시도했으며,이 질문은 MySQL에 문제가되지 않았다는 것을 나타냅니다. 계속해서 SQL Server를 사용하여 CTE를 사용하여 쿼리를 리팩터링 한 다음 다시 중첩 된 쿼리 (남아있는 경우)로 다시 변환합니다. 서식에 대해 죄송합니다. Jeff Atwood는 저에게 원래 게시 된 텍스트를 보냈고 다시 개조해야했습니다.

데이터, 예상 결과 및 좋은 이름 없이는하기가 어렵지만 중첩 된 쿼리를 CTE로 변환하고, 쌓고, 의미있게 이름을 지정하고, 리팩터를 사용하지 않고 리팩터를 사용하지 않습니다. 최적화가 똑똑하기 때문에 열을 제거하면 개선이 발생하지 않을 것입니다. 그러나 쿼리를 개선 할 수있는 기능을 제공합니다. 아마도 CTE의 일부 또는 전부를 고려할 수 있습니다. 코드가 무엇을하고 있는지 잘 모르겠지만, 새로운 랭크 ()-유형 함수가 유용하다는 것을 알 수 있습니다. 왜냐하면이 모든자가 요인과 함께 탐색 유형의 패턴을 사용하고있는 것처럼 보이기 때문입니다.

대신 여기에서 시작하십시오. E7에서 사용되지 않은 열은 그룹화 가능성에 대한 결함 또는 불완전한 생각을 나타낼 수 있지만, 이러한 열이 실제로 불필요하다면 E6의 논리를 통해 완전히 물러날 수 있습니다. E5 및 E3. E7의 그룹화가 올바른 경우 결과와 조인의 MAX (ID)를 제외한 모든 것을 제거 할 수 있습니다. 카테고리 당 여러 최대 (ID)가있는 이유를 알 수 없습니다. 결합시 결과가 곱하기 때문에 MAX (ID)는 범주 내에서 고유해야하므로 카테고리가 조인에서 중복됩니다.

WITH e3 AS (
select min(e1.rank) as rank,
e1.entity,
e1.provider_id,
e1.service_date
from table_a e1
where e1.site_id is not null
group by e1.entity, e1.provider_id, e1.service_date
)

,e5 AS (
select max(e2.id) as id,
e3.rank,
e2.entity,
e2.provider_id,
e2.service_date
from table_a e2
inner join e3
on e2.rank= e3.rank
and e2.entity = e3.entity
and e2.provider_id = e3.provider_id
and e2.service_date = e3.service_date
and e2.rank= e3.rank
group by e2.entity, e2.provider_id, e2.service_date, e3.rank
)

,e6 AS (
select e4.* -- switch from * to only the columns you are actually using
from table_a e4
inner join e5
on e4.id = e5.id
and e4.rank= e5.rank
)

,e7 AS (
select max(e6.id) as id, e6.category -- unused, e6.entity, e6.service_date
from e6
group by e6.category, e6.entity, e6.service_date
-- This instead
-- select max(e6.id) as id
-- from e6
-- group by e6.category, e6.entity, e6.service_date
)

select e8.*
from table_a e8
inner join e7
on e8.id = e7.id
and e7.category = e8.category
-- THIS INSTEAD on e8.id = e7.id

다른 팁

효율적인 인덱스를 사용할 수있는 경우 100,000 행이 13 초가 걸리지 않아야합니다. SQL Server가 MySQL보다 훨씬 강력한 쿼리 최적화기를 가지고 있다는 사실 때문이라고 생각합니다. MySQL이 가진 것은 최적화보다 SQL 파서의 순서에 더 가깝습니다.

초보자를 위해 모든 참여 테이블의 전체 스키마와 각각의 전체 인덱스 목록 - 더 많은 정보를 제공해야합니다.

그런 다음 데이터의 내용과 쿼리가 생성하려는 내용에 대한 몇 가지 아이디어. 사용 사례의 순서에 관한 것.

차이점이 무엇인지 확인하기 위해 계획을 설명하는 것이 흥미로울 것입니다. 나는 그것이 사과와 오렌지 비교인지 확실하지 않지만 궁금 할 것입니다.

나는 모르겠다 이것 도움이 될 수 있지만 이것은 "MySQL Query Optimizer"를 검색 한 첫 번째 타격이었습니다.

여기에 있습니다 다른 것 그것은 가치가있을 수 있습니다.

CTE를 가지고있는 사람이 아는 유일한 오픈 소스 데이터베이스는 Firebird입니다.http://www.firebirdsql.org/rlsnotesh/rlsnotes210.html#rnfb210-cte)

Postgres는 8.4로 생각합니다

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