2014-06-14 17 views
0

常見口號是總是寧願PreparedStatement而不是Statement,因爲它可以防止SQL注入和性能提高(顯着)。不重複使用PreparedStatements時的性能影響?

但是如果我的代碼一遍又一遍地重建相同的PreparedStatement而不是正確地重用它呢?

對於使用Statement仍然有一些性能好處嗎,還是我爲字符串參數留下了重量級引號轉義引擎?

回答

1

通過Statement重建PreparedStatement仍然有優勢,但它將取決於供應商。例如,在Oracle中,爲了不破壞服務器的sql緩存,使用綁定變量是很好的做法。

Oracle服務器會對sql字符串進行哈希以查看它是否已存在於Oracle服務器的sql高速緩存中。如果是這樣,語句的高速緩存的代碼可以重新使用。在這種情況下,解析,驗證,檢查授權等工作已經完成,只需要更新參數區域。此外,由於不需要將新語句放在那裏,SQL緩存的使用將會最小化。

在設計糟糕的應用程序,我們將看到SQL緩存完全一樣的語句:從客戶端接收

SELECT wage FROM employee WHERE employee_id = 1 
SELECT wage FROM employee WHERE employee_id = 2 
SELECT wage FROM employee WHERE employee_id = 3 
SELECT wage FROM employee WHERE employee_id = 4 

這些語句不會導致在SQL緩存緩存命中,所以所有的解析工作需要再次完成,並將新的語句添加到緩存中。不僅有解析語句的額外工作,但緩存變得無用,因爲它充斥着這些東西。在設計良好的應用程序中,您可能可以調整sql緩存的大小,以使應用程序運行後的每個語句都可以在緩存中運行。

我們將查詢字典表,計算具有相似前綴的語句以查找這些違規者,獲取應用程序代碼以使用綁定參數(如果它是Java代碼,則請開發人員使用PreparedStatements)。然後我們會在緩存中看到類似這樣的語句:

SELECT wage FROM employee WHERE employee_id = :1 

單個語句。如果客戶端將其作爲Prepared語句反覆重建,則它無關緊要,只要它出現相同的緩存命中。

+0

我很疑惑,爲什麼Oracle不會過濾來自查詢的文字以增加「簡單」查詢的緩存命中數。任何人都有解釋,爲什麼這不會產生像參數化查詢所實現的相同的緩存結果? – Timo

+0

較新的版本可能。我的經驗是在Oracle 7到11之間。在以後的版本中,有一個名爲'CURSOR_SHARING'的服務器配置選項,它看起來類似於過濾文字,但它不是默認的,並且具有其他效果。我們仍然檢查了緩存,並回復了應用程序開發人員有關未作爲準備好的聲明的聲明。 – Glenn