2016-02-28 48 views
0

我剛剛遇到一些奇怪的性能差異。兩個非常相似的選擇語句不同的性能

我有兩個選擇:

SELECT s.dwh_end_date, 
     t.*, 
     '-1' as PROMOTION_DROP_EMP_CODE, 
     trunc(sysdate +1) as PROMOTION_END_DATE, 
     'K01' as PROMOTION_DROP_REASON, 
     -1 as PROMOTION_DROP_WO_NUMBER 
FROM STG_PROMO_EXPIRE_DATE t 
INNER JOIN fct_customer_services s 
ON(t.dwh_product_key = s.dwh_product_key) 

這需要大約20秒。

這一個:

SELECT s.dwh_end_date, 
     s.dwh_product_key, 
     s.promotion_expire_date, 
     s.PROMOTION_DROP_EMP_CODE, 
     s.PROMOTION_END_DATE, 
     s.PROMOTION_DROP_REASON, 
     s.PROMOTION_DROP_WO_NUMBER 
FROM STG_PROMO_EXPIRE_DATE t 
INNER JOIN fct_customer_services s 
ON(t.dwh_product_key = s.dwh_product_key) 

這大約需要400秒

他們基本上是相同的 - 它只是,以確保我已經更新了我的數據正確(第一選擇是更新FCT表)第二選擇,以確保每件事情都正確更新。

這兩個選擇之間的唯一區別是我選擇的列。 (STG表有兩列 - dwh_p_key和prom_expire_date)?

First select explain plan

Second select explain plan

什麼可能導致此怪異的行爲..

的FCT表建立索引UNIQUE(dwh_product_key,dwh_end_date)和按dwh_end_date(2.5億條記錄)分區,STG沒有任何索引(及其僅有的15k條記錄)

在此先感謝。

+4

請粘貼解釋計劃,並沒有圖像 –

+0

那些時間是返回所有行還是僅返回結果的第一頁?如果您重複運行兩個查詢,它們是否一致?或者您是否正在看到塊緩存的效果?並且這些計劃是*不相同的,再次查看底部的兩行以及字節值。索引全掃描與全表掃描是一個重要的區別。 –

+0

@AlexPoole你是對的,沒有用我的眼睛看到它..是的,他們反覆,無論我運行多少次這些結果..爲什麼這種戲劇性的差異發生? – Yossi

回答

3

該計劃是不是完全一樣。第一個查詢使用fct_customer_services上的索引快速完整掃描,並且不需要訪問實際表中的任何塊,因爲您只能引用兩個索引列。

第二個查詢確實需要訪問表格塊才能獲取其他無偏列的列值。它正在進行全表掃描 - 比完整索引掃描更慢,更昂貴。優化器沒有看到使用索引,然後訪問特定錶行的任何改進,大概是因爲基數太高 - 它需要訪問太多的錶行以通過首先觸擊索引來節省任何努力。這樣做會更慢。

所以第二個查詢比較慢,因爲它必須從磁盤/緩存中讀取整個表而不是整個索引,並且該表比索引大得多。您可以查看分配給兩個對象(索引和表)的段以查看它們的大小比例。

+0

但是,如果查詢已經訪問了tabled並獲得了dwh_product_key,爲什麼在選擇另一列從同一行需要不同的訪問表? – Yossi

+0

@Yossi - 在第一個查詢中,只需查看索引即可同時獲得dwh_product_key(用於連接)和dwh_end_date(用於選擇列表)。其他表格欄中不需要任何其他內容。在第二個查詢中,promotion_expire_date在該索引中是* not *,它僅在實際表中。它不會訪問表兩次,它會執行一次全表掃描以獲取dwh_product_key **和**所需的所有其他列值,以供選擇丟失。 –

+0

太好了,謝謝。 @AlexPoole – Yossi

相關問題