2009-06-14 32 views
5

Tôi có một tình huống tham gia cơ sở dữ liệu chung liên quan đến ba bảng. Một bảng, A, là bảng chính có khóa chính có tên là id. Bảng B và C chứa dữ liệu phụ cho các mục nhập và A, và mỗi cột cũng có một cột có tên là id là khóa ngoại chỉ đến A. id. Bây giờ, nếu tôi muốn tất cả dữ liệu từ A, B và C trong một truy vấn, tôi sẽ viết:Bổ sung các điều kiện tham gia vào kết quả Oracle trong một kế hoạch khác

SELECT * 
FROM A 
INNER JOIN B 
ON B.id = A.id 
INNER JOIN C 
ON C.id = A.id 

khóa học nào hoạt động hoàn hảo.

Gần đây, DBA của chúng tôi nói với chúng tôi rằng đây là không hiệu quả trong Oracle, và bạn cần phải tham gia vào điều kiện giữa C và B là tốt, như sau:

SELECT * 
FROM A 
INNER JOIN B 
ON B.id = A.id 
INNER JOIN C 
ON C.id = A.id AND C.id = B.id 

này trông dư thừa đối với tôi, vì vậy tự nhiên tôi đã không không tin ở đây. Cho đến khi tôi thực sự chạy vào một truy vấn chậm mà có một kế hoạch thực hiện khủng khiếp, và quản lý để sửa chữa nó bằng cách thêm chính xác điều kiện tham gia bị thiếu. Tôi chạy giải thích kế hoạch trên cả hai phiên bản: một trong những không có điều kiện truy vấn "dư thừa" có chi phí 1 035 trong khi "cải thiện" một có 389 (và có sự khác biệt rất lớn trong cardinality và byte là tốt). Cả hai truy vấn đều cho ra kết quả tương tự.

Có ai có thể giải thích tại sao điều kiện bổ sung này tạo sự khác biệt không? Với tôi C và B thậm chí không liên quan. Cũng lưu ý rằng nếu bạn lấy đi điều kiện kết nối khác thì nó cũng không kém phần quan trọng - cả hai đều cần phải ở đó.

Trả lời

2

Điều bạn gặp phải là hai vấn đề.Trước tiên, với SQL ban đầu, trình tối ưu hóa ước tính số hàng trong A với các hàng khớp với ID trong B cũng có hàng phù hợp trong C. Ước tính không chính xác và kế hoạch sai được chọn .

Bây giờ, bạn thêm điều kiện dự phòng. Oracle giả định rằng không có điều kiện nào thực sự dư thừa (như, nếu chúng là, một nhà phát triển thông minh sẽ không bao gồm chúng). Nó cũng giả định rằng mỗi điều kiện là độc lập với những người khác. Ví dụ, một lựa chọn mà tóc = 'hói' có thể nhận được 10% của một bảng, một lựa chọn nơi giới tính = 'F' có thể nhận được 50%. Oracle sẽ giả định rằng một lựa chọn nơi tóc = 'hói' và giới tính = 'F' sẽ cung cấp cho 5% (trong khi trong thực tế hói đầu chủ yếu là giới hạn cho nam giới).

Bằng cách thêm vị từ 'dư thừa', Oracle sẽ ước tính quá nhiều số hoặc hàng cần loại trừ và sẽ chọn gói phù hợp.

Nếu, với biến vị ngữ dư thừa, Oracle đang chọn một kế hoạch tốt hơn, nó gợi ý rằng các ước tính cho truy vấn ban đầu được ước tính vượt quá số hàng phù hợp. Các vị từ dự phòng là chống lại rằng với một ước tính dưới. Và trong trường hợp này, hai sai lầm đang tạo ra một quyền.

Nó không phải là một giải pháp tôi muốn giới thiệu, nhưng nếu nó hoạt động .....

PS. Tôi giả sử kiểu dữ liệu của tất cả các ID là nhất quán. Nếu B.ID và C.ID là ngày và A.ID là ký tự, hoặc ngược lại, thì có thể có một số hàng có A.ID = B.ID và A.ID = C.ID nhưng B.ID! = C.ID, bởi vì chuyển đổi ngầm có thể mất dấu thời gian.

+1

Tôi đồng ý với bạn Gary: nếu kế hoạch tốt hơn với điều kiện tham gia dự phòng, đó là do số liệu thống kê không chính xác. Nói chung, bạn KHÔNG nên cung cấp thông tin dư thừa. –

+0

Đây là câu trả lời hấp dẫn nhất đối với tôi, bởi vì nó phục hồi một số hy vọng trong Oracle. (Vì vậy, có, tôi là một chút không công bằng thiên vị.) Cho dù đó là lời giải thích thực tế là khó khăn cho bất cứ ai để trả lời. – waxwing

1

Hai truy vấn này trông không giống với tôi chút nào.
Sau đó, một lần nữa tôi không phải là trình tối ưu hóa của Oracle.

Bởi vì cả B và C có phím nước ngoài của A khi bạn đã làm điều này

INNER JOIN B 
ON B.id = A.id 

resultset kết quả (nói rằng một vài lần nhanh) mà bạn tham gia bảng C trong truy vấn thứ hai của bạn là nhỏ hơn, như bạn thấy trong kết quả thực hiện kế hoạch của bạn, hơn là khi bạn tham gia bảng C chỉ vào bảng A như trong truy vấn đầu tiên của bạn. Vì vậy, bạn đã tối ưu hóa mọi thứ trong truy vấn thứ hai bằng cách tham gia bảng C trên tập dữ liệu nhỏ hơn là giao điểm của A và B, tập dữ liệu nhỏ hơn là giao điểm của A và C.

+1

Heartily không đồng ý. Việc thêm điều kiện thứ hai sẽ không có sự khác biệt với kích thước tập kết quả thực tế. Như đã lưu ý bởi những người khác, nó thay đổi ước tính của trình tối ưu hóa về kích thước tập hợp kết quả, do đó thay đổi trong kế hoạch thực hiện. Thật sai khi nói rằng anh ấy đã tham gia bảng C "chỉ với bảng A" trong truy vấn đầu tiên; ông gia nhập A và B, sau đó gia nhập C vào tập hợp kết quả đó. Điều kiện kết nối xảy ra chỉ tham chiếu một cột trong A, nhưng một cách hợp lý các cột ID trong cả ba bảng được yêu cầu phải bằng nhau bởi các điều kiện kết nối, vì vậy các kết quả giống nhau bất kể cái nào được sử dụng. –

+0

@Dave: Cảm ơn bạn đã giải thích kỹ lưỡng. Tôi cảm thấy rằng tôi đã học được rất nhiều từ việc cung cấp một câu trả lời nghèo cho câu hỏi này. Hy vọng rằng ai đó khác cũng có thể học hỏi được điều này. – bernie

2

Trình tối ưu hóa của Oracle không đưa ra các giả định chuyển tiếp về bình đẳng. Mặc dù chúng ta hiểu rằng nếu A = B và A = C, thì B = C, Oracle không cho rằng có mối quan hệ giữa B & C trừ khi có một tuyên bố rõ ràng trong mệnh đề WHERE hoặc JOIN. Tôi giả sử bạn có những ràng buộc khác về A, B và/hoặc C (trái với việc chỉ chọn toàn bộ nội dung của các bảng - nếu không thì I/O của bạn sẽ không quá thấp trừ khi các bảng của bạn quá nhỏ, tại đó tối ưu hóa điểm là phần nào tranh luận). Vì vậy, thực sự có nhiều ràng buộc trên A, B & C so với những gì bạn chỉ định. Trình tối ưu hóa của Oracle sẽ xem xét tất cả các bảng trong mệnh đề FROM, liệt kê các ràng buộc đối với chúng trong mệnh đề WHERE, và sau đó xác định tính chọn lọc của các ràng buộc dựa trên các chỉ mục cho các bảng đó. Sau đó nó sẽ đi qua các hoán vị khác nhau của kế hoạch tấn công và xác định đó mang lại hy vọng nhất (đó là những giá trị cardinality bạn nhìn thấy trong kế hoạch). Nếu không có điều kiện B = C, nó sẽ loại trừ các kế hoạch bắt đầu bằng B và tiến tới C (hoặc ngược lại), và đó có thể là các kế hoạch tốt nhất có thể.

+0

Vâng, giả định của bạn là chính xác. Trong thực tế, tôi thậm chí không thể tìm thấy truy vấn ban đầu khi tôi viết câu hỏi này, vì vậy tôi đã viết một câu hỏi tương tự bao gồm ba bảng với các mối quan hệ đã nói. Tôi có một câu hỏi rằng truy vấn thực tế đã tạo ra những khác biệt ấn tượng hơn nữa. Tuy nhiên, tôi đã thử (với truy vấn ban đầu) chỉ bao gồm điều kiện B = C (nhưng không phải là A = C), và có kết quả tương tự xấu. Điều kỳ lạ đối với tôi là tôi phải có cả A = C và B = C. – waxwing

3

Thú vị.

Có vẻ như Oracle có thể phỏng đoán sự bình đẳng chuyển tiếp này chỉ trong một số trường hợp: Họ gọi nó là Transitive Closure và bạn sẽ có thể hưởng lợi từ nó khi ghi lại truy vấn được bật.

Nhưng để an toàn, hãy tự mình viết chính xác vị từ dự phòng.

+0

Bài viết thú vị. Cảm ơn! – waxwing

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