2012-10-15 69 views
1

我有二十年的SQL經驗,但沒有專門與Oracle。一個「甲骨文專家」向我保證,建立一個SQL查詢,而無需參數(像這樣):Oracle Perfomance - JDBC Oracle Thin驅動程序:是否使用參數?

SELECT t.ID, t.Name, t.Address ... FROM Table1 t WHERE t.ID = 'someID' AND t.Name = 'someName'... 

至少是儘可能快地使用

SELECT t.ID, t.Name, t.Address ... FROM Table1 t WHERE t.ID = ? AND t.Name = ? 

的代碼中執行參數(像這樣)一個循環。

在大多數其他數據庫我有經驗,使用參數提高速度。它允許數據庫緩存與SQL語句相匹配的編譯計劃。由於SQL不會在每次調用時發生更改(儘管這些參數會這樣做),因此可以提高性能。數據庫只是綁定參數並繼續。

'Oracle專家'聲明這不是必需的。但顯然,Oracle需要「解析」參數,將剩餘的字符串與緩存的執行計劃匹配,然後重新綁定參數,就好像它們首先作爲參數傳遞一樣。

我在這裏有正確的心理照片嗎? Oracle有什麼「神奇」的東西,它確實對我們如何處理參數傳遞/ SQL構建策略沒有影響?

有沒有關於Java/JDBC/Oracle瘦驅動程序的想法,我不知道我應該知道這裏?

我正在尋找要麼加強我的理解,要麼擴大我的知識。 (請注意安全問題,我知道構建SQL字符串可以進行SQL注入攻擊,我正在尋找更直接的彈藥來對付專家意見 - 如果存在的話)。

其他詳情:Oracle 11gR2, Java 1.6

回答

4

說不過去 - 你說的對,你的Oracle專家似乎根本就不是專家(除非他想賣出昂貴的諮詢時間一旦您投入生產,可加速您的應用程序)。

如果構建不帶參數的SQL語句(在Oracle中稱爲綁定變量),則強制數據庫在每次執行時都強制解析語句。

請參閱AskTom on soft/hard parsing and bind variables以獲得更好的解釋。

1

我沒有做任何性能測試,但我認爲你的圖片是正確的。在任何情況下,即使它們同樣快,我總是更喜歡使用參數/綁定變量的變體來防止SQL注入。在你的例子中,你的where子句中有固定的字符串可能不是問題,但在實際應用中,這些字符串通常來自外部的某個地方。 (我認爲你編輯了你的問題,當我剛剛寫下這個答案時:-))

+0

;) - 對我來說,SQL注入就足夠了。感謝您幫助我構建案例。 – cmdematos

3

使用參數幾乎總是可取的。如果使用文字(第一版),則會有數千個略有不同的SQL語句觸發數據庫,​​導致硬解析並填充Oracle的語句緩存。

這是規則的一個例外:如果您要查詢值非常不均勻分佈的列,則帶有文字的版本可能允許查詢優化器找到更好的計劃。

例如,假設絕大多數Slashdot的讀者是男性(*),

select * from slashdot_readers where gender='MALE'; 

可能會導致查詢優化器上gender忽視的指標,做一個全表掃描代替,而

select * from slashdot_readers where gender='FEMALE'; 

可能會導致它使用索引。使用變量時,查詢優化器將不知道要使用哪個版本,因此它可能會始終執行全表掃描。

(*)只是爲了這個例子

+0

請牢記邊緣案例的好處 - 謝謝! – cmdematos

1

做一些測量。獲取數據。

從我對Oracle的一切瞭解 - 你應該是對的。很顯然,請確定它是否在循環中,並重新執行相同的PreparedStatement,而不是每次重新準備它。這可以降低查詢的成本。

有一點需要注意 - 您的真實應用程序可能會受益於連接變量而不是簡單的測試用例,因爲在實際應用程序中Oracle會在其緩存中擁有各種其他SQL語句(我忘記了目前在Oracle中不同的內存區域和緩存的術語),並且隨着時間的推移,新SQL的發送成本不斷上漲。

+0

+1表示硬解析字符串將緩存中的其他緩存語句擠出。 – cmdematos

相關問題