Đây là một kịch bản mới xuất hiện gần đây tại nơi làm việc.
Xét ba bảng A, B, C.
A có 3.000 hàng; B có 300.000.000 hàng; và C có 2.000 hàng.
Các khóa ngoại được định nghĩa: B (a_id), B (c_id).
Giả sử bạn có một truy vấn giống như sau:
select a.id, c.id
from a
join b on b.a_id = a.id
join c on c.id = b.c_id
Theo kinh nghiệm của tôi, MySQL có thể chọn C -> B -> A trong trường hợp này. C nhỏ hơn A và B là rất lớn, và tất cả chúng đều bằng nhau.
Vấn đề là MySQL không nhất thiết phải tính đến kích thước của phần giao nhau giữa (C.id và B.c_id) so với (A.id và B.a_id). Nếu phép nối giữa B và C trả về nhiều hàng bằng B, thì đó là một lựa chọn rất tồi; nếu bắt đầu bằng A sẽ lọc bớt B xuống nhiều hàng bằng A, thì đó sẽ là lựa chọn tốt hơn nhiều. straight_join
có thể được sử dụng để buộc đơn đặt hàng này như thế này:
select a.id, c.id
from a
straight_join b on b.a_id = a.id
join c on c.id = b.c_id
Bây giờ a
phải được tham gia vào trước đây b
.
Nói chung, bạn muốn thực hiện các phép nối của mình theo một thứ tự giảm thiểu số hàng trong tập hợp kết quả. Vì vậy, bắt đầu với một bảng nhỏ và tham gia sao cho kết quả tham gia cũng sẽ nhỏ, là lý tưởng. Mọi thứ sẽ diễn ra theo hình quả lê nếu bắt đầu với một chiếc bàn nhỏ và ghép nó vào một chiếc bàn lớn hơn thì kết thúc cũng chỉ lớn bằng chiếc bàn lớn.
Tuy nhiên, nó phụ thuộc vào số liệu thống kê. Nếu phân phối dữ liệu thay đổi, tính toán có thể thay đổi. Nó cũng phụ thuộc vào chi tiết triển khai của cơ chế tham gia.
Các trường hợp tồi tệ nhất mà tôi đã thấy đối với MySQL mà tất cả ngoại trừ straight_join
gợi ý chỉ mục bắt buộc hoặc tích cực là các truy vấn phân trang trên nhiều dữ liệu theo thứ tự sắp xếp nghiêm ngặt với tính năng lọc ánh sáng. MySQL rất thích sử dụng các chỉ mục cho bất kỳ bộ lọc nào và tham gia nhiều loại; điều này có ý nghĩa bởi vì hầu hết mọi người không cố gắng sắp xếp toàn bộ cơ sở dữ liệu mà chỉ có một tập hợp con giới hạn các hàng đáp ứng với truy vấn và việc sắp xếp một tập hợp con giới hạn nhanh hơn nhiều so với lọc toàn bộ bảng, bất kể nó được sắp xếp hay không phải. Trong trường hợp này, đặt nối thẳng ngay sau bảng có cột được lập chỉ mục mà tôi muốn sắp xếp theo những thứ cố định.
straight_join
.