2016-11-23 72 views
3

我有一個需要17秒才能執行的查詢。我已經在FIPS,STR_DT,END_DT上應用了索引,但仍然需要時間。關於如何改善表現的任何建議?改善Oracle中的聯接查詢

我的查詢:

SELECT /*+ALL_ROWS*/ K_LF_SVA_VA.NEXTVAL VAL_REC_ID,  a.REC_ID, 
    b.VID, 
    1 VA_SEQ, 
    51 VA_VALUE_DATATYPE, 
    b.VALUE VAL_NUM, 
    SYSDATE CREATED_DATE, 
    SYSDATE UPDATED_DATE 
    FROM CTY_REC a JOIN FIPS_CONS b 
ON a.FIPS=b.FIPS AND a.STR_DT=b.STR_DT AND a.END_DT=b.END_DT; 


DESC CTY_REC; 

Name    Null Type   
------------------- ---- ------------- 
REC_ID     NUMBER(38)  
DATA_SOURCE_DATE   DATE   
STR_DT     DATE   
END_DT     DATE   
VID_RECSET_ID   NUMBER   
VID_VALSET_ID   NUMBER   
FIPS      VARCHAR2(255) 


DESC FIPS_CONS; 

Name   Null  Type   
------------- -------- ------------- 
STR_DT     DATE   
END_DT     DATE   
FIPS     VARCHAR2(255) 
VARIABLE    VARCHAR2(515) 
VALUE     NUMBER   
VID   NOT NULL NUMBER   

解釋計劃:

Plan hash value: 919279614 

-------------------------------------------------------------- 
| Id | Operation   | Name       | 
-------------------------------------------------------------- 
| 0 | SELECT STATEMENT |        | 
| 1 | SEQUENCE   | K_VAL       | 
| 2 | HASH JOIN   |        | 
| 3 | TABLE ACCESS FULL| CTY_REC      | 
| 4 | TABLE ACCESS FULL| FIPS_CONS      | 
-------------------------------------------------------------- 

我添加表的描述和我的查詢說明計劃。

+1

有多少行,表中替換/*+ all_rows */?從查詢中投影了多少行?在另一個表中,哪些行的比例不匹配行?什麼是序列的緩存值? –

+0

你能展示完整的執行計劃嗎?包括行估計和成本列(也許TmpSpc) –

回答

3

在它的面前,沒有您所使用的順序,排在每個表的數量,以及配置信息從查詢中計算出的總行數,可能是您執行計劃是返回所有行的效率最高的計劃。

優化器清楚地認爲索引不會使性能受益,並且在優化所有行而不是第一行時通常更有可能。基於索引的訪問一次只能有一個單獨的塊和一個行,因此在每個塊的基礎上,它本質上可能比多塊全面掃描慢。

Oracle正在使用的散列連接是連接數據集的極其有效的方式。除非散列表如此大以至於溢出到磁盤,否則總成本僅比兩個表的完整掃描略高。我們需要更詳細的執行統計信息,以便能夠判斷散列表是否溢出到磁盤,並且如果解決方案可能只是修改了內存管理,而不是索引。

如果序列的緩存值非常低且記錄數很高,那麼可能會阻塞您的SQL執行的操作是調用該序列。需要更多信息 - 如果你需要爲每一行生成一個順序標識符,那麼你可以使用ROWNUM。

+1

我喜歡這個回答。你說得對,全表掃描本身不是很糟糕。它們有時是訪問數據的最有效方式。而且,是的,散列連接是連接兩個表格的一種很好的技術。 –

0

這基本上是你的查詢:

SELECT . . . 
FROM CTY_REC a JOIN 
    FIPS_CONS b 
    ON a.FIPS = b.FIPS AND a.STR_DT = b.STR_DT AND a.END_DT = b.END_DT; 

你想在(FIPS, STR_DT, END_DT)一個綜合指數,也許這兩個表:

create index idx_cty_rec_3 on cty_rec(FIPS, STR_DT, END_DT); 
create index idx_fipx_con_3 on cty_rec(FIPS, STR_DT, END_DT); 

事實上,只有一個可能是必要的,但同時具有給出了優化更多的選擇來改善查詢。

+0

我已經有這些。 – dang

0

你至少應該有在桌子上這兩個指標:

  • CTY_REC(FIPS,STR_DT,END_DT)
  • FIPS_CONS(FIPS,STR_DT,END_DT)

它仍然可以被加速與覆蓋索引代替:

  • CTY_REC(FIPS,STR_DT,END_DT,·REC_ID)
  • FIPS_CONS(FIPS,STR_DT,END_DT,價值,VID)
+0

當您包含所需的rowid和空格時,這些索引可能會比表格大。 –

+0

@David Aldridge:是的,有時候索引會變大,但我不會認爲這是不使用它們的原因。 –

0

如果你想開車到使用索引優化,
/*+ first_rows */