我在升級到Oracle 11g後優化Oracle查詢時遇到問題,並且此問題開始讓我有點生氣。在分佈式查詢上禁用綁定窺視功能嗎?
請注意,這個問題現在已經完全編輯了,因爲在創建一個簡單的測試用例之後我有更多的信息。原始問題可以在這裏找到:https://stackoverflow.com/revisions/12304320/1。
此問題是,如果連接兩個表(其中一個表在日期列中有一個between
條件),如果查詢連接到遠程表,綁定窺視不會發生。
這是一個測試用例,幫助重現問題。首先設置兩個源表。首先是日期的列表,是在第一個月的,要追溯到30年前
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
);
然後一些數據從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;
然後創建一個空表在運行數據到:
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;
然後運行代碼。您可能需要創建更大版本的mike_temp_dba_objects以減慢查詢速度(或使用其他某種方法來獲取執行計劃)。在查詢運行時,我通過從不同的會話運行select * from table(dbms_xplan.display_cursor(sql_id => 'xxxxxxxxxxx'))
來從會話中獲得執行計劃。
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;
通過查詢有遠程表,基數估計爲mike_temp_etl_control表是完全錯誤的,綁定窺測似乎並沒有發生。
對於上面的查詢執行計劃如下:
---------------------------------------------------------------------------------------
| 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)|
---------------------------------------------------------------------------------------
如果我然後與本地版本替換遠程dual
我得到正確的基數(139代替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)|
-------------------------------------------------------------------------------------
所以,我想問題是我怎樣才能得到正確的基數來估計?這是一個Oracle錯誤還是這是預期的行爲?
爲了擺脫容易的東西,你重新收集[統計](http://docs.oracle.com/cd/E11882_01/server.112/e25494/general002.htm#ADMIN11525)在桌子上? – Ben
是的,統計數據應該都是新鮮的。儘管明天會再次檢查。它是數據倉庫ETL負載的一部分,隨着它的發展,統計數據會聚到一切 –
我知道在版本> 11.1中有一個錯誤,其中包含將「_optim_peek_user_binds」參數設置爲false的全面工作。這可以影響優化器,但我不知道如何。您可以檢查此參數設置爲true還是false,對於最高性能應該是正確的。該錯誤會導致ORA-3137錯誤。 – Gisli