2016-09-02 63 views
4

我們在生產中有一個獨特的問題。在我們的批處理週期中,我們的Oracle 12c數據庫不時會在半夜中掛起。我們將不得不重新啓動數據庫以繼續進行幾天/每週。然後它再次發生。 一些挖後,我們已經把範圍縮小到這個SQL:Oracle中的神祕笛卡爾更新

UPDATE c_bill SET reason_desc = (SELECT description FROM codes 
WHERE code_group = 'TRANSACTION_TYPE' AND code = c_bill.reason_code); 

我已經改名爲表 - 但碼錶有代碼和說明。開發人員正在嘗試將描述從此複製到c_bill表。

此SQL是作爲批處理作業的一部分每晚運行的存儲過程的一部分。開發人員在此之前做了另一次更新,通過很好,但這個SQL需要很長時間。

在特定的運行過程中,該表有36308行。當我檢查生產DB(我看看V $ SQL表獲得的SQL),我看到以下內容:

Rows_processed爲第1更新36308 Rows_processed對於上述更新1318270864,那happpens是= 36308 * 36308! (笛卡爾積?)

我們在測試中沒有這個問題。當我嘗試UPDATE並解釋它在TEST中計劃時,沒有問題 - 它在UPDATE和v $ sql中都顯示了正確的36308行。

這是令人費解的。有沒有人在SQL中看到笛卡爾產品的機會?或者您是否瞭解Oracle 12c優化器中的任何錯誤,可能會將其變成笛卡爾產品(我們只是使用一些補丁修復了Group by by的錯誤)。

我有相當數量的Oracle經驗 - 我在這裏調查查詢。我建議開發人員添加一個where條件來確保。我們尚未對此進行測試。與此同時,我想通過甲骨文專家的採訪。任何意見/建議非常感謝。

更新:任何人都希望在這個崗位在將來 - 的問題不是笛卡爾乘積,但問題SQL更新在日同表的遊標循環中運行,因此看起來像笛卡爾。見Justin的答案。

+1

'v $ sql'中的'executions' 1?或者是36308(即語句在每個36308次執行中更新了36308行)?你能得到該語句的查詢計劃(來自共享池還是來自AWR/Statspack)以查看它是否實際上具有笛卡爾積?'c_bill'是否有名爲'code_group'或'code'的列或只存在於'codes'中的列? –

+0

我想你可能已經釘了它!執行= 36308並且是它所在的過程,它有一個光標,用於獲取c_bill表中的鍵的行。前面提到的更新實際上有遊標SQL中使用的鍵,但是這個沒有。我會做更多的測試並回傳。我不是DBA,我會在下週檢查AWR的統計數據(他們現在已經很長時間了!)。你可以請回復作爲答案? – SamV

+0

再次從v $ sql中,問題UPDATE語句的last_load_time是last_load_time是2016-09-02/03:04:02 而last_active_time是09/02/2016 4:48。這是否意味着同一個SQL在那個小時內保持運行36308次? – SamV

回答

1

我的第一個想法是嘗試收集證據,證實這一證據可以證實或駁斥理論證明你有一個做笛卡爾乘積的錯誤計劃。是executions in v$sql 1?還是36308?如果它是1,那將支持笛卡爾乘積理論,並且我將開始查找v$sql_plandba_hist_sql_plan中的查詢計劃,具體取決於發生何時以及您是否有權使用AWR。另一方面,如果它是36308,那麼這意味着查詢正在更新36308行,但是由於某些內容試圖遍歷表中的每一行,導致它被調用36308次。

+0

很好的答案!幫助查明這個謎團。當數據庫管理員今天早上從網格控制器發送了最新的活動圖表時,看起來像一個SQL正在花費那麼長時間。就像你所說的那樣,實際上它是在1小時內保持多次運行的緩存SQL。今天早上剛開始看問題 - 錯過了外層循環使用了同一張表。感謝您爲我縮小範圍! – SamV

1

我不知道你在這裏描述的行爲的任何特定原因。無論如何,作爲一種解決方法,你可以嘗試用一個備用更新,比如這個:

UPDATE 
    (SELECT c_bill.reason_desc oldDesc, codes.description newDesc 
    FROM c_bill INNER JOIN codes ON 
     code.code_group = 'TRANSACTION_TYPE' AND 
     codes.code = c_bill.reason_code) 
SET oldDesc = newDesc 

不幸的是,我很難真正嘗試在Oracle這個說法現在。我知道我以前看過這種更新。

+0

感謝@Zoran的建議。我試過了,它肯定會增加它缺乏的地方。但是SQL並沒有比以前的版本做得更好。基於賈斯汀凱的評論,我看着處決,它在那裏執行36308次!所以,我認爲SQL在一個循環內部沒有條件導致它看起來像笛卡兒積。我會在測試後回覆我的發現。 – SamV

+1

你的問題非常豐富,我想我們都從中學到了一些東西。 –