Có sự khác biệt thực thi giữa điều kiện THAM GIA và điều kiện WHERE không?


17

Có sự khác biệt về hiệu năng giữa hai truy vấn mẫu này không?

Truy vấn 1:

select count(*)
from   table1 a
join   table2 b
on     b.key_col=a.key_col
where  b.tag = 'Y'

Truy vấn 2;

select count(*)
from   table1 a
join   table2 b
on     b.key_col=a.key_col
   and b.tag = 'Y'

Lưu ý sự khác biệt duy nhất là vị trí của điều kiện bổ sung; cái đầu tiên sử dụng WHEREmệnh đề và cái thứ hai thêm điều kiện vào ONmệnh đề.

Khi tôi chạy các truy vấn này trên hệ thống Teradata của mình, các kế hoạch giải thích giống hệt nhau và bước THAM GIA hiển thị điều kiện bổ sung trong từng trường hợp. Tuy nhiên, đối với câu hỏi SO này liên quan đến MySQL, một trong những câu trả lời cho rằng kiểu thứ hai được ưa thích hơn vì WHEREquá trình xử lý xảy ra sau khi các phép nối được thực hiện.

Có một quy tắc chung để tuân theo khi mã hóa truy vấn như thế này? Tôi đoán nó phải phụ thuộc vào nền tảng vì rõ ràng nó không tạo ra sự khác biệt trên cơ sở dữ liệu của tôi, nhưng có lẽ đó chỉ là một tính năng của Teradata. Và nếu nó nền tảng phụ thuộc, tôi muốn rất nhiều để có được một vài tài liệu tham khảo tài liệu hướng dẫn; Tôi thực sự không biết phải tìm gì.


9
Nó phụ thuộc vào nền tảng, vì nó phụ thuộc vào cách trình tối ưu hóa RDBMSes xử lý phân tích cú pháp và tối ưu hóa.
Phil

8
Và câu trả lời trong câu hỏi được liên kết xứng đáng với một số downvote. Ngay cả trình tối ưu hóa nguyên thủy của MySQL cũng hiểu rằng các truy vấn đơn giản này là tương đương và "mệnh đề WHERE được đánh giá sau khi tất cả các phép nối được thực hiện" chỉ đúng ở mức logic, không phải trong thực thi thực tế.
ypercubeᵀᴹ

1
Không thực sự là một bản sao; câu hỏi đó và các câu trả lời đã so sánh cú pháp THAM GIA "ngầm" với "rõ ràng". Tôi đang hỏi cụ thể về điều kiện tham gia bổ sung.
BellevueBob

Sẽ không dám đăng một câu trả lời như tôi đã thử trước đây và nhận được rất nhiều phiếu bầu. Khi có nhiều liên kết tôi có các trường hợp kinh nghiệm đưa điều kiện lên tham gia dẫn đến một kế hoạch truy vấn tốt hơn (nó được lọc sớm). Vẫn kết quả như vậy.
paparazzo

Câu trả lời:


14

Theo Chương 9 (Trình phân tích cú pháp và Trình tối ưu hóa), Trang 172 của cuốn sách Tìm hiểu nội bộ MySQL của Sasha Pachev

Hiểu nội bộ MySQL

Dưới đây là phân tích đánh giá của một truy vấn như các tác vụ sau:

  • Xác định các khóa nào có thể được sử dụng để truy xuất các bản ghi từ các bảng và chọn khóa tốt nhất cho mỗi bảng.
  • Đối với mỗi bảng, hãy quyết định xem quét bảng có tốt hơn không khi đọc trên khóa. Nếu có nhiều bản ghi khớp với giá trị khóa, các ưu điểm của khóa sẽ giảm và quá trình quét bảng trở nên nhanh hơn.
  • Xác định thứ tự các bảng sẽ được nối khi có nhiều hơn một bảng trong truy vấn.
  • Viết lại các mệnh đề WHERE để loại bỏ mã chết, giảm các tính toán không cần thiết và thay đổi các ràng buộc bất cứ nơi nào có thể để mở đường cho việc sử dụng các khóa.
  • Loại bỏ các bảng không sử dụng từ tham gia.
  • Xác định xem các phím có thể được sử dụng cho ORDER BYGROUP BY.
  • Cố gắng đơn giản hóa các truy vấn con, cũng như xác định mức độ kết quả của chúng có thể được lưu trữ.
  • Hợp nhất các khung nhìn (mở rộng tham chiếu khung nhìn dưới dạng macro)

Trên cùng một trang, nó nói như sau:

Trong thuật ngữ tối ưu hóa MySQL, mỗi truy vấn là một tập hợp các phép nối. Thuật ngữ tham gia được sử dụng ở đây rộng hơn trong các lệnh SQL. Một truy vấn chỉ có một bảng là một phép nối suy biến. Mặc dù chúng ta thường không nghĩ rằng đọc các bản ghi từ một bảng như một phép nối, các cấu trúc và thuật toán tương tự được sử dụng với các phép nối thông thường hoạt động hoàn hảo để giải quyết truy vấn chỉ với một bảng.

TIẾNG VIỆT

Do có các khóa hiện tại, số lượng dữ liệu và biểu hiện của truy vấn, MySQL Joins đôi khi có thể làm mọi việc vì lợi ích của chúng tôi (hoặc để lấy lại cho chúng tôi) và đưa ra kết quả mà chúng tôi không mong đợi và không thể giải thích nhanh chóng.

Tôi đã viết về sự khó chịu này trước đây

bởi vì Trình tối ưu hóa truy vấn MySQL có thể loại bỏ một số khóa nhất định trong quá trình đánh giá truy vấn.

Nhận xét của @ Phil giúp tôi xem cách đăng câu trả lời này (+1 cho nhận xét của @ Phil)

Nhận xét của @ ypercube (+1 cho bài viết này cũng vậy) là phiên bản rút gọn của bài đăng của tôi vì Trình tối ưu hóa truy vấn của MySQL là nguyên thủy. Thật không may, nó phải được kể từ khi nó liên quan đến các công cụ lưu trữ bên ngoài.

PHẦN KẾT LUẬN

Đối với câu hỏi thực tế của bạn, Trình tối ưu hóa truy vấn MySQL sẽ xác định số liệu hiệu suất của từng truy vấn khi hoàn thành

  • đếm hàng
  • chọn phím
  • mát xa tập kết quả không liên tục
  • Ồ vâng, thực hiện THAM GIA

Bạn có thể sẽ phải ép buộc thứ tự thực hiện bằng cách viết lại (tái cấu trúc) truy vấn

Đây là truy vấn đầu tiên bạn đưa ra

select count(*)
from   table1 a
join   table2 b
on     b.key_col=a.key_col
where  b.tag = 'Y';

Hãy thử viết lại để đánh giá WHERE trước

select count(*)
from   table1 a
join   (select key_col from table2 where tag='Y') b
on     b.key_col=a.key_col;

Điều đó chắc chắn sẽ thay đổi kế hoạch GIẢI THÍCH. Nó có thể tạo ra kết quả tốt hơn hoặc xấu hơn.

Tôi đã từng trả lời một câu hỏi trong StackOverflow nơi tôi đã áp dụng kỹ thuật này. EXPLAIN là khủng khiếp nhưng hiệu suất là động lực. Nó chỉ hoạt động vì có các chỉ mục chính xác hiện tại và việc sử dụng GIỚI HẠN trong truy vấn con .

Cũng như giá cổ phiếu, khi nói đến Truy vấn và cố gắng thể hiện chúng, các hạn chế được áp dụng, kết quả có thể thay đổi và hiệu suất trong quá khứ không biểu thị cho kết quả trong tương lai.


2
+1 cho thông tin cụ thể về MySQL và đặc biệt là lừa tôi tìm hiểu sự khác biệt giữa "Phần kết" và "Kết luận"!
BellevueBob

Trong bài viết của tôi, phần kết là một kết luận phụ.
RolandoMySQLDBA

6
@Rolando: Bạn có thể thêm Hậu quả về các cải tiến trên trình tối ưu hóa trong các phiên bản MariaDB (5.3 và 5.5) mới nhất và trong phiên bản MySQL (5.6) chính được phát hành gần đây. Mà có thể làm cho một số viết lại không cần thiết.
ypercubeᵀᴹ

1

Đối với Oracle, do myQuery có một mô tả dài, chúng tôi đã có 2 cách cao để tận dụng trình tối ưu hóa.

Đầu tiên là Tối ưu hóa dựa trên quy tắc (hoặc RBO). Oracle có 15 quy tắc được thiết lập sẵn mà mỗi truy vấn mà nó phân tích cú pháp sẽ cố gắng tuân theo thứ tự đã đặt. Nếu nó không thể tạo ra một truy vấn được tối ưu hóa từ quy tắc 1, nó sẽ chuyển sang quy tắc 2 trở đi cho đến khi đạt được quy tắc 15.

để biết thêm thông tin: https://docs.oracle.com/cd/B10500_01/server.920/a96533/rbo.htm

Những điều này ảnh hưởng đến các nhân Oracle RDBMS từ 11.1 trở xuống chưa được chuyển đổi thành Trình tối ưu hóa dựa trên chi phí (còn gọi là CBO). Oracle 11.2 trở lên yêu cầu trình tối ưu hóa CBO, nhưng có thể buộc các ID Sql cụ thể phải tối ưu hóa trong phương thức RBO cũ nếu người dùng muốn.

Thay vào đó, CBO cho Oracle 11.1+ thực hiện một số kế hoạch thực hiện cho cùng một ID SQL và thực hiện kế hoạch có chi phí dự kiến ​​ít nhất. Nó tận dụng rất nhiều logic từ RBO, nhưng phân tích số liệu thống kê bảng để tạo chi phí kế hoạch thực hiện động cho mỗi hoạt động mà DB phải làm để cung cấp cho người dùng cuối dữ liệu của họ. Thực hiện quét toàn bộ bảng trên các bảng rất lớn thực sự tốn kém; thực hiện quét toàn bộ bảng trên một bảng có 10 hàng là rẻ. Trong RBO, chúng được coi là hoạt động như nhau.

để biết thêm thông tin: https://oracle-base.com/articles/misc/cost-basing-optimizer-and-database-statistic

Đối với ví dụ truy vấn cụ thể của bạn: Oracle có thể phân tích thông tin để thực hiện các kế hoạch thực hiện khác nhau và do đó, một kế hoạch sẽ tốt hơn về mặt kỹ thuật. Tuy nhiên, đây có thể là một sự khác biệt tối thiểu. Nhìn vào nó, cả Oracle RBO và CBO đều muốn truy vấn thêm 1 vì nó đang thực hiện một phép nối với điều kiện ít hơn và sau đó lọc ra một cột cụ thể từ bảng tạm thời mà nó tạo ra từ phép nối.


1

Nếu bạn có hai truy vấn và bạn nghĩ rằng chúng tương đương nhau thì điều sau đây có thể xảy ra:

  1. Cả hai truy vấn có cùng một kế hoạch thực hiện. Điều đó là tốt và đó là những gì chúng ta mong đợi. Hãy hy vọng rằng đó là kế hoạch thực hiện tối ưu cho truy vấn.
  2. có kế hoạch thực hiện khác nhau. Chúng tôi có hai subcase ở đây.

    2.1 Các truy vấn có kế hoạch thực hiện khác nhau nhưng cả hai kế hoạch đều hoạt động tốt như nhau. Điều đó cũng tốt Không cần thiết cho các truy vấn tương đương, cùng một kế hoạch phải được tạo. Nhưng hiệu suất nên bằng nhau. Và một lần nữa chúng tôi hy vọng rằng nó là tốt nhất có thể.

    2.2 Các truy vấn có kế hoạch thực hiện khác nhau và một kế hoạch tốt hơn so với kế hoạch khác. Một lần nữa chúng ta có các nhóm con:

    2.2.1 Các kế hoạch là khác nhau vì các truy vấn không tương đương. Vì vậy, cẩn thận kiểm tra nếu chúng thực sự tương đương. Trong trường hợp của bạn họ thực sự là tương đương.

    2.2.2 Các kế hoạch là khác nhau nhưng các truy vấn là tương đương. Điều này có nghĩa là trình tối ưu hóa không đủ trưởng thành. Trong một thế giới hoàn hảo với tối ưu hóa hoàn hảo, điều này không nên xảy ra. Vì vậy, có, nó phụ thuộc vào nền tảng và bạn phải nghiên cứu các tài liệu cụ thể về nền tảng để tìm hiểu lý do tại sao điều này xảy ra.

    2.2.3 Các kế hoạch là khác nhau, các truy vấn là tương đương, phần mềm cơ sở dữ liệu có lỗi.

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.