1. 程式人生 > >MySQL-SQL繫結變數

MySQL-SQL繫結變數

認識繫結變數

繫結變數是為了減少解析的,比如你有個語句這樣

select aaa,bbb from ccc where ddd=eee;

如果經常通過改變eee這個謂詞賦值來查詢,像如下

select aaa,bbb from ccc where ddd=fff;
select aaa,bbb from ccc where ddd=ggg;
select aaa,bbb from ccc where ddd=hhh;

每條語句都要被資料庫解析一次,這樣比較浪費資源,如果把eee換成“:1”這樣的繫結變數形式,無論ddd後面是什麼值,都不需要重複解析。

Java實現繫結變數的方法:

[java] view plaincopy
PreparedStatement pstmt = con.prepareStatement("UPDATE employees SET salay = ? WHERE id = ?");  
pstmt.setBigDecimal(1, 15.00);  
pstmt.setInt(2, 110592);   
/result statmement:   UPDATE employees SET salay = 15.00 WHERE id = 110592  
pstmt.executeQuery(); 

假設要將id從1到10000的員工的工資都更新為150.00元,不使用繫結變數,則:

[java] view plaincopy
sql.executeQuery("UPDATE employees SET salay = 150.00 WHERE id = 1");  
sql.executeQuery("UPDATE employees SET salay = 150.00 WHERE id = 2");  
sql.executeQuery("UPDATE employees SET salay = 150.00 WHERE id = 3");  
sql.executeQuery("UPDATE employees SET salay = 150.00 WHERE id = 4");  
....  
sql.executeQuery("
UPDATE employees SET salay = 150.00 WHERE id = 10000");

使用繫結變數,則:

[java] view plaincopy
PreparedStatement pstmt;  
for (id = 1; id < 10000; id  )  
{  
  if (null == pstmt)  
    pstmt = con.prepareStatement("UPDATE employees SET salay = ? WHERE id = ?");  
  pstmt.setBigDecimal(1, 150.00);  
  pstmt.setInt(2, id);   
  pstmt.executeQuery();  
}  

二者區別在於,不用繫結變數,則相當於反覆解析、執行了1w個sql語句。使用繫結變數,解析sql語句只用了一次,之後的9999次複用第一次生成的執行計劃。顯然,後者效率會更高一些。

什麼時候不應該/不必要使用繫結變數

  • 如果你用資料倉庫,一條大查詢一跑幾個小時,根本沒必要做繫結變數,因為解析的消耗微乎其微。
  • 變數對優化器產生執行計劃有很重要的影響的時候:繫結變數被使用時,查詢優化器會忽略其具體值,因此其預估的準確性遠不如使用字面量值真實,尤其是在表存在資料傾斜(表上的資料非均勻分佈)的列上會提供錯誤的執行計劃。從而使得非高效的執行計劃被使用。