SQL kết hợp với truy vấn con SQL (Hiệu suất)?


110

Tôi muốn biết nếu tôi có một truy vấn tham gia như thế này -

Select E.Id,E.Name from Employee E join Dept D on E.DeptId=D.Id

và một truy vấn con như thế này -

Select E.Id,E.Name from Employee Where DeptId in (Select Id from Dept)

Khi tôi xem xét hiệu suất , truy vấn nào trong hai truy vấn sẽ nhanh hơn và tại sao ?

Ngoài ra, có khi nào tôi nên thích cái này hơn cái kia không?

Xin lỗi nếu điều này là quá tầm thường và đã hỏi trước đây nhưng tôi đang bối rối về nó. Ngoài ra, sẽ thật tuyệt nếu các bạn có thể gợi ý cho tôi các công cụ tôi nên sử dụng để đo hiệu suất của hai truy vấn. Cảm ơn rất nhiều!


5
@Lucero, câu hỏi này được gắn thẻ sql-server-2008, trong đó bài đăng bạn đề cập được gắn thẻ MySql. Bạn có thể suy ra rằng các câu trả lời sẽ giống nhau. Tối ưu hóa hiệu suất được thực hiện khác nhau trên hai RDBMS.
Francois Botha

Câu trả lời:


48

Tôi mong đợi truy vấn đầu tiên sẽ nhanh hơn, chủ yếu là vì bạn có một hàm tương đương và một THAM GIA rõ ràng. Theo kinh nghiệm của tôi INlà một toán tử rất chậm, vì SQL thường đánh giá nó như một loạt các WHEREmệnh đề được phân tách bằng "OR" ( WHERE x=Y OR x=Z OR...).

Như với TẤT CẢ NHỮNG ĐIỀU trong SQL, số dặm của bạn có thể khác nhau. Tốc độ sẽ phụ thuộc rất nhiều vào chỉ mục (bạn có chỉ mục trên cả hai cột ID không? Điều đó sẽ giúp ích rất nhiều ...) trong số những thứ khác.

Cách THỰC SỰ duy nhất để biết chắc chắn 100% cái nào nhanh hơn là bật theo dõi hiệu suất (Thống kê IO đặc biệt hữu ích) và chạy cả hai. Đảm bảo xóa bộ nhớ cache của bạn giữa các lần chạy!


16
Tôi thực sự nghi ngờ về câu trả lời này, vì hầu hết DBMS, chắc chắn là SQL Server 2008 trở lên, dịch truy vấn con ID duy nhất (không tương quan, nghĩa là: không tham chiếu đến nhiều cột truy vấn bên ngoài) thành một phép nối bán tương đối nhanh. Ngoài ra, như đã lưu ý trước đây trong một câu trả lời khác, kết hợp thực đầu tiên sẽ trả về một hàng cho MỖI sự xuất hiện của ID phù hợp trong Dept - điều này không có gì khác biệt đối với một ID duy nhất, nhưng sẽ cung cấp cho bạn rất nhiều bản sao ở những nơi khác. Sắp xếp những thứ này với DISTINCT hoặc GROUP BY sẽ là một tải hiệu suất nặng khác. Kiểm tra các kế hoạch thực thi trong SQL Server Management Studio!
Erik Hart

2
Mệnh đề IN tương đương với OR áp dụng cho danh sách tham số / giá trị, nhưng không áp dụng cho các truy vấn con, hầu hết được coi như các phép nối.
Erik Hart

42

Tôi tin rằng đó là một câu hỏi "Cũ nhưng vàng". Câu trả lơi con phụ thuộc vao nhiêu thư!". Các buổi biểu diễn là một chủ đề tế nhị đến nỗi sẽ là quá ngớ ngẩn nếu nói: "Không bao giờ sử dụng truy vấn phụ, hãy luôn tham gia". Trong các liên kết sau, bạn sẽ tìm thấy một số phương pháp hay nhất cơ bản mà tôi thấy là rất hữu ích:

Tôi có một bảng với 50000 phần tử, kết quả tôi đang tìm kiếm là 739 phần tử.

Truy vấn của tôi lúc đầu là:

SELECT  p.id,
    p.fixedId,
    p.azienda_id,
    p.categoria_id,
    p.linea,
    p.tipo,
    p.nome
FROM prodotto p
WHERE p.azienda_id = 2699 AND p.anno = (
    SELECT MAX(p2.anno) 
    FROM prodotto p2 
    WHERE p2.fixedId = p.fixedId 
)

và mất 7,9 giây để thực thi.

Cuối cùng truy vấn của tôi là:

SELECT  p.id,
    p.fixedId,
    p.azienda_id,
    p.categoria_id,
    p.linea,
    p.tipo,
    p.nome
FROM prodotto p
WHERE p.azienda_id = 2699 AND (p.fixedId, p.anno) IN
(
    SELECT p2.fixedId, MAX(p2.anno)
    FROM prodotto p2
    WHERE p.azienda_id = p2.azienda_id
    GROUP BY p2.fixedId
)

và mất 0,0256 giây

SQL tốt, tốt.


3
Thật thú vị, bạn có thể giải thích cách thêm GROUP BY đã khắc phục sự cố này không?
cozos

6
Bảng tạm thời được tạo bởi truy vấn con nhỏ hơn. Do đó, quá trình thực hiện nhanh hơn vì có ít dữ liệu hơn để kiểm tra.
Bản thân tôi

2
Tôi nghĩ rằng trong truy vấn đầu tiên, bạn đã chia sẻ biến giữa truy vấn bên ngoài và truy vấn con, vì vậy đối với mỗi hàng trong truy vấn chính, truy vấn phụ sẽ thực thi nhưng trong truy vấn thứ hai, truy vấn con chỉ thực hiện một lần và theo cách này, hiệu suất được cải thiện.
Ali Faradjpour

1
Máy chủ Sql và MySql và ... Sql (ngoại trừ NoSql) rất giống nhau về cơ sở hạ tầng. Chúng tôi có một loại công cụ tối ưu hóa truy vấn bên dưới để chuyển đổi các mệnh đề IN (...) để tham gia (nếu có thể). Nhưng khi bạn có một Nhóm theo trên một cột được lập chỉ mục tốt (dựa trên số lượng của nó) thì nó sẽ nhanh hơn nhiều. Vì vậy, nó thực sự phụ thuộc vào tình hình.
Alix

10

Bắt đầu xem xét các kế hoạch thực thi để xem sự khác biệt về cách SQl Server sẽ diễn giải chúng. Bạn cũng có thể sử dụng Profiler để thực sự chạy các truy vấn nhiều lần và nhận được sự khác biệt.

Tôi không mong đợi những điều này sẽ khác nhau kinh khủng, nơi bạn có thể nhận được hiệu suất thực sự, tăng hiệu suất lớn khi sử dụng các phép nối thay vì các truy vấn con khi bạn sử dụng các truy vấn con tương quan.

EXISTS thường tốt hơn một trong hai cách này và khi bạn đang nói các phép nối bên trái mà bạn muốn tất cả các bản ghi không có trong bảng nối bên trái, thì NOT EXISTS thường là lựa chọn tốt hơn nhiều.


9

Hiệu suất dựa trên lượng dữ liệu bạn đang thực thi trên ...

Nếu nó là ít dữ liệu hơn khoảng 20k. JOIN hoạt động tốt hơn.

Nếu dữ liệu giống hơn 100k + thì IN hoạt động tốt hơn.

Nếu bạn không cần dữ liệu từ bảng khác, IN là tốt, Nhưng tốt hơn là nên chọn EXISTS.

Tất cả các tiêu chí này tôi đã thử nghiệm và các bảng có chỉ mục phù hợp.


4

Hiệu suất phải giống nhau; điều quan trọng hơn là áp dụng các chỉ mục và phân cụm chính xác trên các bảng của bạn (có một số tài nguyên tốt về chủ đề đó).

(Đã chỉnh sửa để phản ánh câu hỏi cập nhật)


4

Hai truy vấn có thể không tương đương về mặt ngữ nghĩa. Nếu một nhân viên làm việc cho nhiều bộ phận (có thể trong doanh nghiệp tôi làm việc; thừa nhận, điều này có nghĩa là bảng của bạn chưa được chuẩn hóa hoàn toàn) thì truy vấn đầu tiên sẽ trả về các hàng trùng lặp trong khi truy vấn thứ hai thì không. Để làm cho các truy vấn tương đương trong trường hợp này, DISTINCTtừ khóa sẽ phải được thêm vàoSELECT mệnh đề, điều này có thể ảnh hưởng đến hiệu suất.

Lưu ý rằng có một quy tắc thiết kế chung quy định rằng bảng phải mô hình hóa một thực thể / lớp hoặc mối quan hệ giữa các thực thể / lớp nhưng không phải cả hai. Do đó, tôi đề nghị bạn tạo một bảng thứ ba, chẳng hạn OrgChart, để mô hình hóa mối quan hệ giữa nhân viên và các phòng ban.


4

Tôi biết đây là một bài viết cũ, nhưng tôi nghĩ đây là một chủ đề rất quan trọng, đặc biệt là ngày nay khi chúng ta có hơn 10 triệu bản ghi và nói về hàng terabyte dữ liệu.

Tôi cũng sẽ cân nhắc với những quan sát sau đây. Tôi có khoảng 45 triệu bản ghi trong bảng của mình ([dữ liệu]) và khoảng 300 bản ghi trong bảng [mèo] của tôi. Tôi có lập chỉ mục mở rộng cho tất cả các truy vấn mà tôi sắp nói đến.

Hãy xem xét Ví dụ 1:

UPDATE d set category = c.categoryname
FROM [data] d
JOIN [cats] c on c.id = d.catid

so với Ví dụ 2:

UPDATE d set category = (SELECT TOP(1) c.categoryname FROM [cats] c where c.id = d.catid)
FROM [data] d

Ví dụ 1 mất khoảng 23 phút để chạy. Ví dụ 2 mất khoảng 5 phút.

Vì vậy, tôi kết luận rằng truy vấn phụ trong trường hợp này nhanh hơn nhiều. Tất nhiên, hãy nhớ rằng tôi đang sử dụng ổ SSD M.2 có khả năng i / o @ 1GB / giây (đó là byte chứ không phải bit), vì vậy các chỉ mục của tôi cũng rất nhanh. Vì vậy, điều này cũng có thể ảnh hưởng đến tốc độ trong trường hợp của bạn

Nếu nó là một lần dọn dẹp dữ liệu, có lẽ tốt nhất là cứ để nó chạy và kết thúc. Tôi sử dụng TOP (10000) và xem mất bao lâu và nhân với số lượng bản ghi trước khi tôi đạt được truy vấn lớn.

Nếu bạn đang tối ưu hóa cơ sở dữ liệu sản xuất, tôi thực sự khuyên bạn nên xử lý trước dữ liệu, tức là sử dụng trình kích hoạt hoặc công việc môi giới để không đồng bộ hóa các bản ghi cập nhật, để truy cập thời gian thực lấy dữ liệu tĩnh.


0

Bạn có thể sử dụng Kế hoạch Giải thích để có được câu trả lời khách quan.

Đối với vấn đề của bạn, bộ lọc Hiện có có thể sẽ hoạt động nhanh nhất.


2
"một bộ lọc Hiện có có thể sẽ hoạt động nhanh nhất" - tôi nghĩ có lẽ không, mặc dù một câu trả lời dứt khoát sẽ yêu cầu thử nghiệm dựa trên dữ liệu thực tế. Bộ lọc hiện có có thể nhanh hơn khi có nhiều hàng có cùng giá trị tra cứu - vì vậy bộ lọc tồn tại có thể chạy nhanh hơn nếu truy vấn đang kiểm tra xem các nhân viên khác đã được ghi lại từ cùng một bộ phận hay chưa, nhưng có lẽ không khi tra cứu một bộ phận bàn.

Nó sẽ chạy chậm hơn trong kịch bản cuối cùng đó?
Snekse

Nó sẽ phụ thuộc vào trình tối ưu hóa - trong những trường hợp nhất định, nó có thể xảy ra, nhưng thông thường tôi sẽ mong đợi hiệu suất rất giống nhau.
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.