Vấn đề tối ưu hóa: các khóa gộp cụm, điều kiện cờ và hợp nhất chỉ mục


11

Ba bảng:

product: với các cột: ( a, g, ...a_lot_more... )

a: PK, clustered
g: bit-column

main: với các cột: ( c, f, a, b, ...a_lot_more... )

c: PK, clustered
f: bit-column
(a, b): UQ 

lookup với các cột: ( a, b, c, i )

(a, b): PK, clustered
a: FK to product(a)
c: UQ, FK to main(c)
i: bit-column

Tôi không thể tìm thấy các chỉ mục tốt cho việc tham gia:

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

Tôi đã thử một chỉ số bao gồm product (g, a, ...)và nó được sử dụng nhưng không có kết quả ngoạn mục.

Một số kết hợp các chỉ mục trên lookupbảng tạo ra các kế hoạch thực hiện với hợp nhất chỉ mục, với mức tăng hiệu quả nhẹ so với kế hoạch trước đó.

Có một số kết hợp rõ ràng mà tôi đang thiếu?

Một thiết kế lại của cấu trúc có thể giúp đỡ?

DBMS là MySQL 5.5 và tất cả các bảng đang sử dụng InnoDB.


Kích thước bảng:

product: 67K   ,  g applied:    64K 

main:   420K   ,  f applied:   190K

lookup:  12M   ,  b,i applied:  67K 

Hãy thử di chuyển các biến vị ngữ bộ lọc vào các phép nối và xem liệu trình tối ưu hóa có làm điều gì đó hợp lý với điều đó không. Tôi đã thấy trình tối ưu hóa của SQL Server thất bại trước đó.
Mối quan tâmOfTunbridgeWells

Trông giống như một sản phẩm của Cartesian vì tôi không thấy bất cứ điều gì THAM GIA từ bảng sản phẩm. Hay là tôi đã bỏ lỡ điều gì ???
RolandoMySQLDBA

@RolandoMySQLDBA: Bạn nói đúng. Tôi sẽ sửa truy vấn.
ypercubeᵀᴹ

Câu trả lời:


3

Điều này làm tôi đau ...

Tôi đã phải sử dụng bảng tạm thời với InnoDB trước đây. Tải chúng bằng các bộ lọc, tạo một chỉ mục, tham gia các bảng tạm thời này.

Vấn đề như tôi nghĩ là nếu InnoDB chỉ có thuật toán Nested Join: trình tối ưu hóa truy vấn RDBMS đã trưởng thành có nhiều thứ để sử dụng hơn. Điều này dựa trên việc thử chạy loại tải Kho dữ liệu trên InnoDB.

Các bảng tạm thời kéo độ phức tạp tổng thể xuống mức tối ưu hóa truy vấn MySQL ...


Thnx, tôi sẽ thử nó. Số lượng hoặc hàng (sau khi các tiêu chí được áp dụng không lớn, tương ứng là 64K, 67K, 190K). Có lẽ tôi nên cố gắng loại bỏ một trong ba bảng ( main) bằng cách không chuẩn hóa dữ liệu vào lookup?
ypercubeᵀᴹ

1
@ypercube: việc không chuẩn hóa sẽ làm cho các hàng rộng hơn, mật độ trang thấp hơn = các vấn đề khác
gbn

3

Nó trông giống như một sản phẩm của Cartesian. Làm lại tiêu chí THAM GIA

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

THAY ĐỔI

Điều này có vẻ không chính thống và có thể có mùi giống như SQL Anitpotype, nhưng ở đây nó ...

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

Tôi đã không di chuyển product.g = 1main.f = 1vào các truy vấn con vì chúng là các trường bit và sẽ chỉ quét bảng tại điểm. Ngay cả khi các trường bit là chỉ mục, Trình tối ưu hóa truy vấn sẽ chỉ bỏ qua một chỉ mục như vậy.

Tất nhiên, bạn có thể thay đổi SELECT * FROM lookupthành SELECT a FROM lookupnếu CHỌN của bạn không cần bất cứ thứ gì từlookup

Có lẽ liên quan đến a, b trong THAM GIA giữa tra cứu và chính nếu điều này có ý nghĩa

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

hoặc đặt lại c và nối trên ba cột (Chỉ mục trên ba cột trong 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

Thnx. Kế hoạch GIẢI THÍCH khác nhau, nhưng hiệu suất tương tự.
ypercubeᵀᴹ

Cardinality của những gì main.fproduct.g??? Nếu giá trị chính của main.fproduct.gcho giá trị là 1 nhỏ hơn 5% số hàng của bảng, một chỉ mục trên main.fproduct.gcó thể chính đáng.
RolandoMySQLDBA

Không sao, họ đã được lập chỉ mục rồi. Nếu cardinality của main.fproduct.glà 2, bạn có thể bỏ các chỉ số đó.
RolandoMySQLDBA

Chỉnh sửa câu hỏi với kích thước bảng và hàng được sử dụng (sau khi các điều kiện được áp dụng).
ypercubeᵀᴹ

Tôi đã cập nhật câu hỏi của mình, đề nghị THAM GIA vào a, b thay vì c. Xem nếu điều đó tạo ra một kế hoạch GIẢI THÍCH khác
RolandoMySQLDBA
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.