세 개의 테이블 :
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