2012-09-06 25 views
8

Tôi đang gặp sự cố khi tối ưu hóa truy vấn Oracle sau khi nâng cấp lên Oracle 11g và vấn đề này đang bắt đầu khiến tôi phát điên.Tính năng xem trộm liên kết có bị tắt trên truy vấn được phân phối không?

Lưu ý, câu hỏi này hiện đã được chỉnh sửa hoàn toàn vì tôi có thêm thông tin sau khi tạo một trường hợp thử nghiệm đơn giản. Câu hỏi ban đầu có sẵn tại đây: https://stackoverflow.com/revisions/12304320/1.

Vấn đề này là khi tham gia hai bảng, một trong số đó có điều kiện between trên cột ngày, nếu truy vấn tham gia vào một bảng điều khiển từ xa, việc xem trộm liên kết không xảy ra.

Đây là trường hợp kiểm tra để giúp tái tạo sự cố. Đầu tiên hãy thiết lập hai bảng nguồn. Đầu tiên là một danh sách các ngày, là người đầu tiên của tháng, sẽ trở lại ba mươi năm

create table mike_temp_etl_control 
as 
select 
    add_months(trunc(sysdate, 'MM'), 1-row_count) as reporting_date 
from (
    select level as row_count 
    from dual 
    connect by level < 360 
); 

Sau đó, một số dữ liệu có nguồn gốc từ dba_objects:

create table mike_temp_dba_objects as 
select owner, object_name, subobject_name, object_id, created 
from dba_objects 
union all 
select owner, object_name, subobject_name, object_id, created 
from dba_objects; 

Sau đó tạo một bảng trống để chạy các dữ liệu trong đến:

create table mike_temp_1 
as 
select 
    a.OWNER, 
    a.OBJECT_NAME, 
    a.SUBOBJECT_NAME, 
    a.OBJECT_ID, 
    a.CREATED, 
    b.REPORTING_DATE 
from 
    mike_temp_dba_objects a 
    join mike_temp_etl_control b on (
     b.reporting_date between add_months(a.created, -24) and a.created) 
    where 1=2; 

Sau đó chạy mã. Bạn có thể cần phải tạo một phiên bản mike_temp_dba_objects lớn hơn để làm chậm truy vấn xuống (hoặc sử dụng một số phương thức khác để có được kế hoạch thực hiện). Trong khi truy vấn đang chạy, tôi nhận được kế hoạch thực hiện từ phiên bằng cách chạy select * from table(dbms_xplan.display_cursor(sql_id => 'xxxxxxxxxxx')) từ một phiên khác.

declare 
    pv_report_start_date date := date '2002-01-01'; 
    v_report_end_date date := date '2012-07-01'; 

begin 

    INSERT /*+ APPEND */ 
    INTO mike_temp_5 
    select 
    a.OWNER, 
    a.OBJECT_NAME, 
    a.SUBOBJECT_NAME, 
    a.OBJECT_ID, 
    a.CREATED, 
    b.REPORTING_DATE 
from 
    mike_temp_dba_objects a 
    join mike_temp_etl_control b on (
    b.reporting_date between add_months(a.created, -24) and a.created) 
    cross join [email protected] -- This line causes problems... 
where 
    b.reporting_date between add_months(pv_report_start_date, -12) and v_report_end_date; 

    rollback; 
end; 

Bằng cách có bảng từ xa trong truy vấn, ước tính thẻ cho bảng mike_temp_etl_control hoàn toàn sai và ràng buộc nhìn trộm dường như không xảy ra.

Các kế hoạch thực hiện cho các truy vấn trên được hiển thị dưới đây:

--------------------------------------------------------------------------------------- 
| Id | Operation    | Name     | Rows | Bytes | Cost (%CPU)| 
--------------------------------------------------------------------------------------- 
| 0 | INSERT STATEMENT   |      |  |  | 373 (100)| 
| 1 | LOAD AS SELECT   |      |  |  |   | 
|* 2 | FILTER     |      |  |  |   | 
| 3 | MERGE JOIN   |      |  5 | 655 | 373 (21)| 
| 4 |  SORT JOIN   |      | 1096 | 130K| 370 (20)| 
| 5 |  MERGE JOIN CARTESIAN|      | 1096 | 130K| 369 (20)| 
| 6 |  REMOTE    | DUAL     |  1 |  |  2 (0)| 
| 7 |  BUFFER SORT  |      | 1096 | 130K| 367 (20)| 
|* 8 |  TABLE ACCESS FULL | MIKE_TEMP_DBA_OBJECTS | 1096 | 130K| 367 (20)| 
|* 9 |  FILTER    |      |  |  |   | 
|* 10 |  SORT JOIN   |      |  2 | 18 |  3 (34)| 
|* 11 |  TABLE ACCESS FULL | MIKE_TEMP_ETL_CONTROL |  2 | 18 |  2 (0)| 
--------------------------------------------------------------------------------------- 

Nếu tôi sau đó thay thế điều khiển từ xa dual với các phiên bản địa phương tôi nhận được cardinality chính xác (139 thay vì 2):

------------------------------------------------------------------------------------- 
| Id | Operation    | Name     | Rows | Bytes | Cost (%CPU)| 
------------------------------------------------------------------------------------- 
| 0 | INSERT STATEMENT  |      |  |  | 10682 (100)| 
| 1 | LOAD AS SELECT  |      |  |  |   | 
|* 2 | FILTER    |      |  |  |   | 
| 3 | MERGE JOIN   |      | 152K| 19M| 10682 (3)| 
| 4 |  SORT JOIN   |      | 438K| 51M| 10632 (2)| 
| 5 |  NESTED LOOPS  |      | 438K| 51M| 369 (20)| 
| 6 |  FAST DUAL  |      |  1 |  |  2 (0)| 
|* 7 |  TABLE ACCESS FULL| MIKE_TEMP_DBA_OBJECTS | 438K| 51M| 367 (20)| 
|* 8 |  FILTER    |      |  |  |   | 
|* 9 |  SORT JOIN   |      | 139 | 1251 |  3 (34)| 
|* 10 |  TABLE ACCESS FULL| MIKE_TEMP_ETL_CONTROL | 139 | 1251 |  2 (0)| 
------------------------------------------------------------------------------------- 

Vì vậy, tôi đoán câu hỏi là làm cách nào để tôi có thể ước tính số lượng thẻ chính xác? Đây có phải là lỗi của Oracle hay đây là hành vi mong đợi không?

+0

Để loại bỏ những thứ dễ dàng, bạn đã thu thập lại [thống kê] (http://docs.oracle.com/cd/E11882_01/server.112/e25494/general002.htm#ADMIN11525) trên bảng? – Ben

+0

Có, các số liệu thống kê tất cả sẽ được tươi. Sẽ kiểm tra lại rằng ngày mai mặc dù. Đó là một phần của tải dữ liệu ETL kho, với số liệu thống kê tập trung vào tất cả mọi thứ khi nó đi –

+0

Tôi biết có lỗi trong phiên bản> 11.1 có vòng lặp hoạt động bao gồm đặt tham số "_optim_peek_user_binds" thành false. Điều này có thể ảnh hưởng đến trình tối ưu hóa nhưng tôi không biết chính xác như thế nào. Bạn có thể kiểm tra xem tham số này được đặt thành true hay false, nó phải đúng cho hiệu suất tối đa. Lỗi này gây ra lỗi ORA-3137. – Gisli

Trả lời

1

Tôi nghĩ bạn nên gây rối về lấy mẫu động. Nó hoạt động trong 11g khác nhau vì vậy nó có thể là lý do của những rắc rối của bạn.

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