SQL預(yù)編譯

1.數(shù)據(jù)庫預(yù)編譯起源

(1)數(shù)據(jù)庫SQL語句編譯特性:
數(shù)據(jù)庫接受到sql語句之后砰粹,需要詞法和語義解析蛛淋,優(yōu)化sql語句咙好,制定執(zhí)行計劃。這需要花費一些時間褐荷。但是很多情況勾效,我們的一條sql語句可能會反復(fù)執(zhí)行,或者每次執(zhí)行的時候只有個別的值不同(比如query的where子句值不同叛甫,update的set子句值不同,insert的values值不同)层宫。
(2)減少編譯的方法
如果每次都需要經(jīng)過上面的詞法語義解析、語句優(yōu)化其监、制定執(zhí)行計劃等萌腿,則效率就明顯不行了。為了解決上面的問題棠赛,于是就有了預(yù)編譯哮奇,預(yù)編譯語句就是將這類語句中的值用占位符替代,可以視為將sql語句模板化或者說參數(shù)化睛约。一次編譯、多次運(yùn)行哲身,省去了解析優(yōu)化等過程辩涝。
(3)緩存預(yù)編譯
預(yù)編譯語句被DB的編譯器編譯后的執(zhí)行代碼被緩存下來,那么下次調(diào)用時只要是相同的預(yù)編譯語句就不需要編譯,只要將參數(shù)直接傳入編譯過的語句執(zhí)行代碼中(相當(dāng)于一個涵數(shù))就會得到執(zhí)行。
并不是所以預(yù)編譯語句都一定會被緩存,數(shù)據(jù)庫本身會用一種策略(內(nèi)部機(jī)制)勘天。
(4) 預(yù)編譯的實現(xiàn)方法
預(yù)編譯是通過PreparedStatement和占位符來實現(xiàn)的怔揩。

2.預(yù)編譯作用:

  • 預(yù)編譯階段可以優(yōu)化 sql 的執(zhí)行
    預(yù)編譯之后的 sql 多數(shù)情況下可以直接執(zhí)行,DBMS 不需要再次編譯脯丝,越復(fù)雜的sql商膊,編譯的復(fù)雜度將越大,預(yù)編譯階段可以合并多次操作為一個操作宠进≡尾穑可以提升性能。
  • 防止SQL注入
    使用預(yù)編譯材蹬,而其后注入的參數(shù)將不會再進(jìn)行SQL編譯实幕。也就是說其后注入進(jìn)來的參數(shù)系統(tǒng)將不會認(rèn)為它會是一條SQL語句,而默認(rèn)其是一個參數(shù)堤器,參數(shù)中的or或者and 等就不是SQL語法保留字了昆庇。

3.預(yù)編譯開啟

(1)數(shù)據(jù)庫是否默認(rèn)開啟預(yù)編譯和JDBC版本有關(guān)。
也可以配置jdbc鏈接時強(qiáng)制開啟預(yù)編譯和緩存:useServerPrepStmts和cachePrepStmts參數(shù)闸溃。預(yù)編譯和預(yù)編譯緩存一定要同時開啟或同時關(guān)閉整吆。否則會影響執(zhí)行效率

conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/prepare_stmt_test?user=root&password=root&useServerPrepStmts=true&cachePrepStmts=true");  

(2)mysql的預(yù)編譯

  • 開啟了預(yù)編譯緩存后拱撵,connection之間,預(yù)編譯的結(jié)果是獨立的表蝙,是無法共享的裕膀,一個connection無法得到另外一個connection的預(yù)編譯緩存結(jié)果。
  • 經(jīng)過試驗勇哗,mysql的預(yù)編譯功能對性能影響不大昼扛,但在jdbc中使用PreparedStatement是必要的,可以有效地防止sql注入欲诺。
  • 相同PreparedStatement的對象 抄谐,可以不用開啟預(yù)編譯緩存。
          conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/prepare_stmt_test?user=root&password=root&useServerPrepStmts=true");  
          PreparedStatement stmt = conn.prepareStatement(sql);  
          stmt.setString(1, "aaa");  
          ResultSet rs1 = stmt.executeQuery();//第一次執(zhí)行  
          s1.close();  
          stmt.setString(1, "ddd");  
          ResultSet rs2 = stmt.executeQuery();//第二次執(zhí)行  
          rs2.close();  
          stmt.close(); 
//查看mysql日志
          1 Prepare          select * from users where name = ?
          1 Execute          select * from users where name = 'aaa'
          1 Execute          select * from users where name = 'ddd'

4.mybatis是如何實現(xiàn)預(yù)編譯的

mybatis 默認(rèn)情況下扰法,將對所有的 sql 進(jìn)行預(yù)編譯蛹含。mybatis底層使用PreparedStatement,過程是先將帶有占位符(即”?”)的sql模板發(fā)送至mysql服務(wù)器塞颁,由服務(wù)器對此無參數(shù)的sql進(jìn)行編譯后浦箱,將編譯結(jié)果緩存,然后直接執(zhí)行帶有真實參數(shù)的sql祠锣。核心是通過#{ } 實現(xiàn)的酷窥。
在預(yù)編譯之前,#{ } 解析為一個 JDBC 預(yù)編譯語句(prepared statement)的參數(shù)標(biāo)記符?伴网。

//sqlMap 中如下的 sql 語句
select * from user where name = #{name};
//解析成為預(yù)編譯語句
select * from user where name = ?;

如果${ }蓬推,SQL 解析階段將會進(jìn)行變量替換。不能實現(xiàn)預(yù)編譯澡腾。

select * from user where name = '${name}'
//傳遞的參數(shù)為 "ruhua" 時,解析為如下沸伏,然后發(fā)送數(shù)據(jù)庫服務(wù)器進(jìn)行編譯。
select * from user where name = "ruhua";
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末动分,一起剝皮案震驚了整個濱河市毅糟,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌澜公,老刑警劉巖姆另,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異玛瘸,居然都是意外死亡蜕青,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進(jìn)店門糊渊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來右核,“玉大人,你說我怎么就攤上這事渺绒『睾龋” “怎么了菱鸥?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長躏鱼。 經(jīng)常有香客問我氮采,道長,這世上最難降的妖魔是什么染苛? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任鹊漠,我火速辦了婚禮,結(jié)果婚禮上茶行,老公的妹妹穿的比我還像新娘躯概。我一直安慰自己,他們只是感情好畔师,可當(dāng)我...
    茶點故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布娶靡。 她就那樣靜靜地躺著,像睡著了一般看锉。 火紅的嫁衣襯著肌膚如雪姿锭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天伯铣,我揣著相機(jī)與錄音呻此,去河邊找鬼。 笑死懂傀,一個胖子當(dāng)著我的面吹牛趾诗,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蹬蚁,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼郑兴!你這毒婦竟也來了犀斋?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤情连,失蹤者是張志新(化名)和其女友劉穎叽粹,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體却舀,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡虫几,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了挽拔。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辆脸。...
    茶點故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖螃诅,靈堂內(nèi)的尸體忽然破棺而出啡氢,到底是詐尸還是另有隱情状囱,我是刑警寧澤,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布倘是,位于F島的核電站亭枷,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏搀崭。R本人自食惡果不足惜叨粘,卻給世界環(huán)境...
    茶點故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望瘤睹。 院中可真熱鬧升敲,春花似錦、人聲如沸默蚌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽绸吸。三九已至鼻弧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間锦茁,已是汗流浹背攘轩。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留码俩,地道東北人度帮。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像稿存,于是被迫代替她去往敵國和親笨篷。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,514評論 2 348

推薦閱讀更多精彩內(nèi)容