2014-09-26 64 views
2

我有一個表,它是在一個數值列(ROW_ID)分區列表,甲骨文分區忽略不工作聯接使用

TABLEA (ROW_ID NUMERIC(38), TB_KEY NUMERIC(38), ROW_DATA VARCHAR(20)); 

分區修整時,我從表中查詢沒有聯接工作

SELECT A.* FROM TABLEA A 
WHERE ROW_ID IN (SELECT ID FROM TABLEB WHERE DT_COL = SYSDATE); 

分區修剪失敗當我左外連接到表B

SELECT A.* FROM TABLEA A 
LEFT OUTER JOIN TABLEB B ON A.TB_KET = B.TB_KEY 
WHERE ROW_ID IN (SELECT ID FROM TABLEB WHERE DT_COL = SYSDATE); 

分區修剪當我改變左外工作加入到內部連接

SELECT A.* FROM TABLEA A 
INNER JOIN TABLEB B ON A.TB_KET = B.TB_KEY 
WHERE ROW_ID IN (SELECT ID FROM TABLEB WHERE DT_COL = SYSDATE); 

分區修剪工作當我做左外連接到表B,並且不使用IN子句

SELECT A.* FROM TABLEA A 
LEFT OUTER JOIN TABLEB B ON A.TB_KET = B.TB_KEY 
WHERE ROW_ID = 123; 

分區修剪工程當我離開外連接到TableB和使用IN子句的靜態值

SELECT A.* FROM TABLEA A 
LEFT OUTER JOIN TABLEB B ON A.TB_KET = B.TB_KEY 
WHERE ROW_ID IN (123, 345); 

有人能解釋一下爲什麼左外連接會導致分區修剪失敗,當我查詢表上的分區使用IN子句與子查詢結果的列?

回答

0

分區修剪可以使用LEFT OUTER JOININ子查詢。您可能會看到一個非常具體的問題,需要更具體的測試用例。

示例模式

drop table tableb purge; 
drop table tablea purge; 

create table tablea (row_id numeric(38),tb_key numeric(38),row_data varchar(20)) 
partition by list(row_id) 
(partition p1 values (1),partition p123 values(123),partition p345 values(345)); 
create table tableb (id numeric(38), dt_col date, tb_key numeric(38)); 

begin 
    dbms_stats.gather_table_stats(user, 'TABLEA'); 
    dbms_stats.gather_table_stats(user, 'TABLEB'); 
end; 
/

查詢

--Partition pruning works when i query from table with no joins: 
explain plan for 
SELECT A.* FROM TABLEA A 
WHERE ROW_ID IN (SELECT ID FROM TABLEB WHERE DT_COL = SYSDATE); 
select * from table(dbms_xplan.display); 

--Partition Pruning fails when I do left outer join to TableB 
explain plan for 
SELECT A.* FROM TABLEA A 
LEFT OUTER JOIN TABLEB B ON A.TB_KEY = B.TB_KEY 
WHERE ROW_ID IN (SELECT ID FROM TABLEB WHERE DT_COL = SYSDATE); 
select * from table(dbms_xplan.display); 

--Partition Pruning works when I change left outer join to inner join 
explain plan for 
SELECT A.* FROM TABLEA A 
INNER JOIN TABLEB B ON A.TB_KEY = B.TB_KEY 
WHERE ROW_ID IN (SELECT ID FROM TABLEB WHERE DT_COL = SYSDATE); 
select * from table(dbms_xplan.display); 

--Partition Pruning works when I do left outer join to TableB and do not use IN clause 
explain plan for 
SELECT A.* FROM TABLEA A 
LEFT OUTER JOIN TABLEB B ON A.TB_KEY = B.TB_KEY 
WHERE ROW_ID = 123; 
select * from table(dbms_xplan.display); 

--Partition Pruning works when I do left outer join to TableB and use static values for IN clause 
explain plan for 
SELECT A.* FROM TABLEA A 
LEFT OUTER JOIN TABLEB B ON A.TB_KEY = B.TB_KEY 
WHERE ROW_ID IN (123, 345); 
select * from table(dbms_xplan.display); 

輸出

這裏不顯示完整的執行計劃,以節省空間。唯一重要的列是PstartPstop,這意味着使用分區修剪。

執行計劃看起來像下列之一:

... ----------------- 
... | Pstart| Pstop | 
... ----------------- 
... 
... | KEY | KEY | 
... | KEY | KEY | 
... 
... ----------------- 

OR 

... ----------------- 
... | Pstart| Pstop | 
... ----------------- 
... 
... |  2 |  2 | 
... |  2 |  2 | 
... 
... ----------------- 

OR 

... ----------------- 
... | Pstart| Pstop | 
... ----------------- 
... 
... |KEY(I) |KEY(I) | 
... |KEY(I) |KEY(I) | 
... 
... ----------------- 

這是如何幫助?

不是很多。儘管您提供的信息比典型問題多得多,但需要更多信息來解決此問題。

至少現在你知道問題不是由分區修剪中的通用限制造成的。這裏有一個非常具體的問題,很可能與優化器統計有關。深入瞭解這些問題可能需要很長時間。我建議從上面的示例數據開始,添加更多的功能和數據,直到分區修剪消失。

通過修改問題在這裏發佈新的測試用例,並且有人應該能夠解決這個問題。