2011-02-10 35 views
7
UPDATE table1 
     SET col1 = 'Y' 
    WHERE col2 in (select col2 from table2) 

Trong truy vấn trên, hãy tưởng tượng truy vấn bên trong trả về 10000 hàng. Truy vấn này với mệnh đề IN có ảnh hưởng đến hiệu suất không?Mệnh đề IN ảnh hưởng như thế nào đến hiệu năng trong oracle?

Nếu có, bạn có thể làm gì để thực hiện nhanh hơn?

+0

Nếu truy vấn con trả về 10000 kết quả, thời gian chạy sẽ bằng 0 khi nó phát ra lỗi. Tôi giả sử bạn muốn viết IN thay vì = cho subselect? –

+0

Bạn đã hiểu. Tôi đã thực hiện thay đổi, cảm ơn bạn. – Vivek

+1

nếu câu trả lời được cung cấp bởi @zerkms hữu ích cho bạn, vui lòng chấp nhận câu trả lời. Kiểm tra Câu hỏi thường gặp để biết lý do bạn nên làm điều này. :-) –

Trả lời

3
UPDATE table1 outer 
    SET col1 = 'Y' 
WHERE EXISTS (select null 
       from table2 
       WHERE col2 = outer.col2) 

Điều này có thể được tốt hơn

Để có được ý tưởng đó là tốt hơn - nhìn vào kế hoạch thực hiện.

+2

Tôi nghĩ rằng đây là một vấn đề được giải quyết trong đó cho trình tối ưu hóa Oracle thường không có sự khác biệt giữa IN và EXISTS và một sẽ được chuyển đổi sang khác khi thích hợp. http://blogs.oracle.com/optimizer/2010/09/optimizer_transformations_subquery_unesting_part_1.html –

11

nếu subquery trả về một số lượng lớn các hàng so với số lượng hàng trong table1, tôi ưu hoa sẽ có khả năng tạo ra một kế hoạch như thế này:

-------------------------------------------------------------------------------- 
| Id | Operation   | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time 
-------------------------------------------------------------------------------- 
| 0 | UPDATE STATEMENT |  | 300K| 24M|  | 1581 (1)| 00:0 
| 1 | UPDATE    | TABLE1 |  |  |  |   | 
|* 2 | HASH JOIN SEMI |  | 300K| 24M| 9384K| 1581 (1)| 00:0 
| 3 | TABLE ACCESS FULL| TABLE1 | 300K| 5860K|  | 355 (2)| 00:0 
| 4 | TABLE ACCESS FULL| TABLE2 | 168K| 10M|  | 144 (2)| 00:0 
-------------------------------------------------------------------------------- 
Predicate Information (identified by operation id): 
--------------------------------------------------- 
    2 - access("COL2"="COL2") 

Nó sẽ quét cả hai bảng một lần và chỉ cập nhật hàng trong TABLE1 chung cho cả hai bảng. Đây là một kế hoạch hiệu quả cao nếu bạn cần cập nhật nhiều hàng.

Đôi khi truy vấn bên trong sẽ có vài hàng so với số hàng trong TABLE1. Nếu bạn có một chỉ mục trên TABLE1(col2), sau đó bạn có thể có được một kế hoạch tương tự như này:

------------------------------------------------------------------------------- 
| Id | Operation   | Name | Rows | Bytes | Cost (%CPU)| Time  | 
------------------------------------------------------------------------------- 
| 0 | UPDATE STATEMENT  |  | 93 | 4557 | 247 (1)| 00:00:03 | 
| 1 | UPDATE    | TABLE1 |  |  |   |   | 
| 2 | NESTED LOOPS  |  | 93 | 4557 | 247 (1)| 00:00:03 | 
| 3 | SORT UNIQUE  |  | 51 | 1326 | 142 (0)| 00:00:02 | 
| 4 |  TABLE ACCESS FULL| TABLE2 | 51 | 1326 | 142 (0)| 00:00:02 | 
|* 5 | INDEX RANGE SCAN | IDX1 |  2 | 46 |  2 (0)| 00:00:01 | 
------------------------------------------------------------------------------- 
Predicate Information (identified by operation id): 
--------------------------------------------------- 
    5 - access("T1"."COL2"="T2"."COL2") 

Trong trường hợp đó Oracle sẽ đọc các hàng từ table2 và cho mỗi (duy nhất) liên tiếp, thực hiện một truy cập chỉ mục trên table1 .

Truy cập nào nhanh hơn phụ thuộc vào tính chọn lọc của truy vấn bên trong và phân nhóm chỉ mục trên TABLE1 (các hàng có giá trị tương tự là col2 trong TABLE1 bên cạnh nhau hoặc phân tán ngẫu nhiên?). Trong mọi trường hợp, hiệu suất khôn ngoan, nếu bạn cần thực hiện cập nhật này, truy vấn này là một trong những cách nhanh nhất để làm điều đó.

+0

Còn truy vấn của tôi thì sao?;-) Xin vui lòng, thêm một kế hoạch thực hiện cho một với 'EXISTS' – zerkms

+3

@zerkms: xin lỗi tôi quên đề cập rằng IN truy vấn phụ được chuyển thành các truy vấn phụ EXIST tương đương bởi trình tối ưu hóa. Do đó, họ sản xuất cùng một kế hoạch. Tôi personnaly tìm thấy IN báo cáo dễ đọc hơn nhưng điều này là rất chủ quan :) –

+0

không biết rằng, cảm ơn. – zerkms

2

Từ Oracle:

11.5.3.4 Sử dụng EXISTS so TRÊN cho các truy vấn con

Trong một số trường hợp, nó là tốt hơn để sử dụng TRÊN chứ không phải là tồn tại. Trong số chung, nếu vị từ chọn lọc là trong truy vấn con, sau đó sử dụng IN. Nếu vị trí chọn lọc nằm trong truy vấn cha mẹ , sau đó sử dụng EXISTS.

Từ kinh nghiệm của tôi, tôi đã thấy các kế hoạch tốt hơn bằng cách sử dụng EXISTS trong đó truy vấn con trả về số lượng lớn hàng.

Xem here để biết thêm thảo luận từ Oracle

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