세 개의 테이블 :
product
: 열 포함 : ( a, g, ...a_lot_more... )
a: PK, clustered
g: bit-column
main
: 열 포함 : ( c, f, a, b, ...a_lot_more... )
c: PK, clustered
f: bit-column
(a, b): UQ
lookup
열이있는 : ( a, b, c, i )
(a, b): PK, clustered
a: FK to product(a)
c: UQ, FK to main(c)
i: bit-column
조인에 대한 좋은 인덱스를 찾을 수 없습니다.
FROM
product
JOIN
lookup
ON lookup.a = product.a
JOIN
main
ON main.c = lookup.c
WHERE
product.g = 1
AND
main.f = 1
AND
lookup.i = 1
AND lookup.b = 17
나는 커버링 인덱스를 시도했지만 product (g, a, ...)
사용되었지만 놀라운 결과는 아닙니다.
lookup
테이블 의 일부 인덱스 조합은 이전 계획에 비해 약간의 효율성 향상과 함께 인덱스 병합으로 실행 계획을 생성합니다.
내가 놓친 명백한 조합이 있습니까?
구조의 재 설계가 도움이 될 수 있습니까?
DBMS는 MySQL 5.5이며 모든 테이블은 InnoDB를 사용하고 있습니다.
테이블 크기 :
product: 67K , g applied: 64K
main: 420K , f applied: 190K
lookup: 12M , b,i applied: 67K
답변
이것은 나를 아프게합니다 …
전에 InnoDB와 함께 임시 테이블을 사용해야했습니다. 필터를 사용하여로드하고 인덱스를 작성하고 이러한 임시 테이블을 결합하십시오.
내가 생각하는 문제는 InnoDB에 Nested Join 알고리즘 만있는 경우입니다. 어른이 된 RDBMS 쿼리 최적화 프로그램이 더 많이 사용해야합니다. 이는 InnoDB에서 데이터웨어 하우스 유형로드를 실행하려는 시도를 기반으로합니다.
임시 테이블은 전체적으로 복잡성을 MySQL 쿼리 최적화 프로그램 수준으로 끌어 놓습니다.
답변
카티 전 곱처럼 보입니다. 가입 기준 다시 실행
FROM
product
JOIN
lookup
ON product.a = lookup.a
JOIN
main
ON main.c = lookup.c
WHERE
product.g = 1
AND
main.f = 1
AND
lookup.i = 1
AND lookup.b = 17
대체 제안
이것은 정통처럼 보이지 않고 SQL Anitpattern과 같은 냄새가 날 수 있지만 여기에 있습니다 …
FROM
product
JOIN
(
SELECT * FROM lookup
WHERE i=1 AND b=17
) lookup ON product.a = lookup.a
JOIN
main ON main.c = lookup.c
WHERE
product.g = 1 AND main.f = 1
나는 움직이지 않았다 product.g = 1
그리고 main.f = 1
그들이 비트 필드이며, 단지 지점에 테이블 스캔을 할 것 때문에 서브 쿼리. 비트 필드가 인덱스 인 경우에도 Query Optimizer는 해당 인덱스를 무시합니다.
물론, 당신은 변경할 수 SELECT * FROM lookup
에 SELECT a FROM lookup
에서 당신의 선택이 필요로하지 않는 경우 아무것도lookup
아마도 룩업과 메인 사이의 JOIN에 a, b가 포함될 수 있습니다.
FROM
product
JOIN
lookup
ON product.a = lookup.a
JOIN
main
ON main.a = lookup.a AND main.b = lookup.b
WHERE
product.g = 1
AND
main.f = 1
AND
lookup.i = 1
AND lookup.b = 17
또는 다시 C를 넣어 (의 3 열에 인덱스를 세 개의 열 조인 main
과 lookup
)
FROM
product
JOIN
lookup
ON product.a = lookup.a
JOIN
main
ON main.a = lookup.a
AND main.b = lookup.b
AND main.c = lookup.c
WHERE
product.g = 1
AND
main.f = 1
AND
lookup.i = 1
AND lookup.b = 17