2011-02-07 10 views
11

Một hệ thống cũ đã đến văn phòng của chúng tôi để có một số thay đổi và sửa chữa, nhưng nó cũng đang gặp vấn đề về hiệu suất. Chúng tôi không biết chính xác nguồn gốc của sự chậm chạp này là gì.Điều gì là tốt hơn? Truy vấn con hoặc tham gia bên trong mười bảng?

Trong khi chúng tôi đã sắp xếp các mã cũ chúng tôi tìm thấy một số truy vấn sql với mô hình sau (các truy vấn được đơn giản hóa cho mục đích ví dụ):

SELECT 
    (
    SELECT X 
    FROM A 
    WHERE A.id = TABLE.id 
    ) AS COLUMN1, 
    (
    SELECT Y 
    FROM B 
    WHERE B.id = TABLE.id 
    ) AS COLUMN1, 
    (
    SELECT Z 
    FROM C 
    WHERE C.id = TABLE.id 
    ) AS COLUMN1, 
    ... 
FROM 
    TABLE 
WHERE 
    TABLE.id = @param; 

Các truy vấn này làm một số truy vấn phụ nội bộ từ mỗi cột họ trở về.

Chúng tôi đang có kế hoạch viết lại các truy vấn trên các mô hình sau:

SELECT 
    A.X, B.Y, C.Z 
FROM 
    TABLE 
    INNER JOIN A on A.ID = TABLE.ID 
    INNER JOIN B on B.ID = TABLE.ID 
    INNER JOIN C on C.ID = TABLE.ID 
WHERE 
    TABLE.id = @param; 

Với bên tham gia họ dễ dàng hơn để đọc và hiểu, nhưng nó thực sự nào nhanh hơn? Có cách nào tốt hơn để viết chúng? Thật không may, lần đầu tiên chúng tôi viết lại không cải thiện thời gian truy vấn, nó làm cho truy vấn chậm hơn một chút.

Đây là câu hỏi của tôi: chúng tôi có nên viết lại tất cả các truy vấn này không? Các truy vấn con này có phải là cách tốt để thực hiện công việc này không? Họ có nhanh hơn cách liên kết bên trong không?

+0

Tom (Kyte, danh tiếng Oracle) đã đưa ra một câu trả lời (và ngắn gọn) tốt cho một câu hỏi rất giống ở đây: ["join with subquery, Exists clause"] (https://asktom.oracle.com/pls/asktom/f? p = 100: 11: 0 :::: P11_QUESTION_ID: 66812779016023) –

Trả lời

14

Nếu tôi hiểu câu hỏi của bạn một cách chính xác, bạn đang bắt đầu một hoạt động để viết lại một số câu lệnh SQL của bạn bởi vì bạn nghĩ rằng có thể có vấn đề với chúng.

Lời khuyên của tôi là dừng lại và trước tiên bắt đầu xác định thời gian của bạn hiện đang được chi tiêu. Chỉ sau khi bạn đã tìm thấy rằng nó trong các truy vấn với các thuê bao vô hướng và đó là vì các thuê bao vô hướng, bạn nên viết lại chúng. Cho đến lúc đó: bắt đầu truy tìm và kiểm tra.

Dưới đây là hai chủ đề từ OTN được sử dụng để hướng dẫn những người có vấn đề hiệu suất:

http://forums.oracle.com/forums/thread.jspa?messageID=1812597 http://forums.oracle.com/forums/thread.jspa?threadID=863295

Kính trọng,
Rob.

Và: vì scalar subquery caching, truy vấn ban đầu của bạn có thể nhanh hơn rất nhiều so với truy vấn được viết lại bằng cách sử dụng kết nối.

+1

Câu trả lời của bạn cho tôi biết chính xác điều gì đó mà tôi không kwon về: "scalar subquery caching". Có lẽ các truy vấn phụ có thể tốt đôi khi. Tuy nhiên, chúng tôi viết lại một truy vấn khác và có kết quả thực sự tốt hơn, từ 0,5 giây đến 0,04 giây. Tôi đang ký bài viết của bạn như là một trong những đúng vì một số người truy vấn phụ có thể là một giải pháp tốt thực sự. Cảm ơn bạn. –

7

truy vấn phụ thực sự chạy một lần cho mỗi hàng trong khi kết hợp xảy ra trên các chỉ mục.

Sử dụng kết nối để dễ đọc hơn và dễ bảo trì hơn như bạn đã đề cập trong các câu hỏi của mình.

+0

Tại sao? nếu có một chỉ mục, nó sẽ áp dụng cho một tìm kiếm id đơn giản. –

+0

Đôi khi bảng không được nối với các cột được lập chỉ mục của chúng. Việc đó có ảnh hưởng đến tùy chọn tham gia nội bộ không? –

+3

@ Adam, @ Gustavo - Hiệu suất phụ thuộc vào công cụ cơ sở dữ liệu mà bạn đang chạy các truy vấn. Bạn phải kiểm tra hiệu suất bằng cách sử dụng kế hoạch thực hiện (không chắc chính xác nó được gọi là gì trong oracle). Đôi khi các truy vấn phụ tốt hơn, đôi khi tham gia, nhưng cuối cùng để có thể đọc và duy trì các truy vấn tốt hơn, các kết nối có một lợi thế nhỏ. –

3

Tham gia sẽ cung cấp cho bạn hiệu suất tốt hơn, nhưng tôi khuyên bạn nên xem xét kế hoạch thực hiện bất cứ khi nào "tối ưu hóa" truy vấn.

+0

Tôi nên theo dõi kế hoạch, cảm ơn. Không có điều chỉnh thực sự mà không đo lường kết quả. –

2

this answer argues, nó nên không ảnh hưởng đến hiệu suất. Tuy nhiên, một số trình tối ưu hóa truy vấn có thể hoạt động tốt hơn trên JOIN, vì vậy bạn nên thực hiện một số thử nghiệm trên hệ thống của mình.

Và bây giờ cho một cái gì đó hoàn toàn khác nhau: JOIN ing mỗi bảng để người tiếp theo có thể là hơn thẩm mỹ hơn JOIN ing tất cả với TABLE, và ngăn ngừa các lỗi bất cứ khi nào id xuất hiện nhiều lần trong một trong các bảng:

SELECT 
    A.X, B.Y, C.Z 
FROM 
    TABLE 
    INNER JOIN A on A.ID = TABLE.ID 
    INNER JOIN B on A.ID = B.ID 
    INNER JOIN C on B.ID = C.ID 
WHERE 
    TABLE.id = @param; 
+0

Cảm ơn bạn về ví dụ. Để chắc chắn nó là tốt hơn để đọc. Trên ví dụ của tôi chỉ có 3 tham gia, nhưng mỗi truy vấn ở đây làm điều đó 10 lần hoặc nhiều hơn cho mỗi truy vấn ... –

Các vấn đề liên quan