SELECT `table_1`.*
FROM `table_1`
INNER JOIN
`table_2` [...]
INNER JOIN
`table_3` [...]
WHERE `table_1`.`id` IN
(
SELECT `id`
FROM [...]
)
AND [more conditions]
Nếu bảng bên trong được lập chỉ mục đúng, truy vấn phụ ở đây không được "thực hiện" một cách nghiêm ngặt.
Do truy vấn phụ là một phần của biểu thức IN
, điều kiện được đẩy vào truy vấn con và nó được chuyển thành một EXISTS
.
Trong thực tế, subquery này được đánh giá trên mỗi bước:
EXISTS
(
SELECT NULL
FROM [...]
WHERE id = table1.id
)
Bạn thực sự có thể nhìn thấy nó trong mô tả chi tiết được cung cấp bởi EXPLAIN EXTENDED
.
Đó là lý do tại sao nó được gọi là DEPENDENT SUBQUERY
: kết quả của mỗi đánh giá tùy thuộc vào giá trị của table1.id
. Truy vấn phụ như vậy không tương quan, đó là phiên bản được tối ưu hóa tương quan.
MySQL
luôn đánh giá mệnh đề EXISTS
sau các bộ lọc đơn giản hơn (vì chúng dễ đánh giá hơn nhiều và có khả năng truy vấn phụ sẽ không được đánh giá).
Nếu bạn muốn subquery được đánh giá tất cả cùng một lúc, viết lại các truy vấn như thế này:
SELECT table_1.*
FROM (
SELECT DISTINCT id
FROM [...]
) q
JOIN table_1
ON table_1.id = q.id
JOIN table_2
ON [...]
JOIN table_3
ON [...]
WHERE [more conditions]
Điều này buộc các subquery được hàng đầu trong tham gia, đó là hiệu quả hơn nếu subquery là nhỏ so đến table_1
và kém hiệu quả hơn nếu truy vấn con lớn hơn so với table_1
.
Nếu có chỉ mục trên [...].id
được sử dụng trong truy vấn phụ, truy vấn phụ sẽ được thực hiện bằng cách sử dụng INDEX FOR GROUP-BY
.
Vấn đề với việc đẩy truy vấn con xuống là điều này là không thể nếu truy vấn con phụ thuộc vào một phần không đổi của truy vấn bên ngoài (xem https://stackoverflow.com/questions/44859809/how-to-optimize-dependent-subquery -with-constant-expression) – andig