카테고리 보관물: Sql

sql

최적화 문제 : 복합 클러스터 키, 플래그 조건 및 인덱스 병합 b): UQ lookup 열이있는 : (

세 개의 테이블 :

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 lookupSELECT 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 열에 인덱스를 세 개의 열 조인 mainlookup)

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

답변