在oracle資料庫中,有乙個變數繫結的用法,很多人都比較熟悉,可以調高資料庫效率,應對高併發等,好吧,這其中並不包括我,當同事問我mysql中有沒有類似的寫法時,我是很茫然的,於是就上網查,找到了如下一種寫法:
view sourceprint?delimiter $$
set @stmt = select userid,username from myuser where userid between ? and ?;
prepare s1 from @stmt;
set @s1 = 2;
set @s2 = 100;
execute s1 using @s1,@s2;
deallocate prepare s1;
delimiter ;
用這種形式寫的查詢,可以隨意替換引數,給出**的人稱之為預處理,我想這個應該就是mysql中的變數繫結吧……但是,在查資料的過程中我卻聽到了兩種聲音,一種是,mysql中有類似oracle變數繫結的寫法,但沒有其實際作用,也就是只能方便編寫,不能提高效率,這種說法在幾個09年的帖子中看到:
另一種說法是mysql中的變數繫結是能確實提高效率的,這個是希望有的,那到底有木有,還是自己去試驗下吧。
試驗是在本機進行的,資料量比較小,具體數字並不具有實際意義,但是,能用來說明一些問題,資料庫版本是mysql-5.1.57-win32免安裝版。
本著對資料庫不是很熟悉的態度^_^,試驗過程中走了不少彎路,此文以結論為主,就不列出實驗的設計過程,文筆不好,文章寫得有點枯燥,寫出來是希望有人來拍磚,因為我得出的結論是:預處理在有沒有cache的情況下的執行效率都不及直接執行…… 我對自己的實驗結果不願接受。。如果說預處理只為了規範下query,使cache命中率提高的話個人覺得大材小用了,希望有比較了解的人能指出事實究竟是什麼樣子的——newsilen
實驗準備
第乙個檔案normalquery.sql
normalquery
set profiling=1;select * from mytable where dictid = 100601000004;select dictid from mytable limit 1,100;select dictid from mytable limit 2,100;/*從limit 1,100 到limit 100,100 此處省略重複***/......select dictid from mytable limit 100,100;select query_id,seq,state,10000*duration from information_schema.profiling into outfile d:/normalresults.csv fields terminated by , lines terminated by
; 第二個sql檔案 stmtquery.sql
stmtquery
set profiling=1;select * from mytable where dictid = 100601000004;set @stmt = select dictid from mytable limit ?,?;prepare s1 from @stmt;set @s = 100;set @s1 = 101;set @s2 = 102;......set @s100 =200;execute s1 using @s1,@s;execute s1 using @s2,@s;......execute s1 using @s100,@s;select query_id,seq,state,10000*duration from information_schema.profiling into outfile d:/stmtresults.csv fields terminated by , lines terminated by
; 做幾點**明:
1. set profiling=1; 執行此語句之後,可以從information_schema.profiling這張表中讀出語句執行的詳細資訊,其實包含不少內容,包括我需要的時間資訊,這是張臨時表,每新開乙個會話都要重新設定profiling屬性才能從這張表中讀取資料
2. select * from mytable where dictid = 100601000004;
這行**貌似和我們的實驗沒什麼關係,本來我也是這麼認為的,之所以加這句,是我在之前的摸索中發現,執行過程中有個步驟是open table,如果是第一次開啟某張表,那時間是相當長的,所以在執行後面的語句前,我先執行了這行**開啟試驗用的表
3. mysql預設在information_schema.profiling表中儲存的查詢歷史是15條,可以修改profiling_history_size屬性來進行調整,我希望他大一些讓我能一次取出足夠的資料,不過最大值只有100,儘管我調整為150,最後能夠查到的也只有100條,不過也夠了
4. sql**我沒有全列出來,因為查詢語句差不多,上面**中用省略號表示了,最後的結果是兩個csv檔案,個人習慣,你也可以把結果存到資料庫進行分析
實驗步驟
重啟資料庫,執行檔案normalquery.sql,執行檔案stmtquery.sql,得到兩個結果檔案
再重啟資料庫,執行stmtquery.sql,執行檔案normalquery.sql,得到另外兩個結果檔案
實驗結果
詳細結果在最後提供了附件**,有興趣的朋友可以看下
結果分析
每乙個sql檔案中執行了一百個查詢語句,沒有重複的查詢語句,不存在查詢cache,統計執行sql的平均時間得出如下結果
從結果中可以看出,無論是先執行還是後執行,normalquery中的語句都比使用預處理語句的要快一些=.=!
那再來看看每一句查詢具體的情況,normal和stmt的query各執行了兩百次,每一步的詳細資訊如下:
從這裡面可以看出,第乙個,normalquery比stmtquery少乙個步驟,第二個,雖然stmt在不少步驟上是優於normal的,但在executing一步上輸掉太多,最後結果上也是落敗
最後,再給出乙個查詢快取的實驗結果,具體步驟就不列了
在查詢快取的時候,normal完勝……
php中使用mysql stmt(預處理語句)
預處理語句在某些應用場合中顯得十分高效和靈活,比如在一些重複查詢或批量資料錄入中。但是認識乙個事物的真面孔往往要經歷一番過程,甚至是折磨。尤其對菜鳥們來說,搞清乙個概念或排除乙個故障,往往要好幾個小時甚至好幾天的時間,箇中滋味自是五花八門啊。閒話少說,言歸正傳。本次系統環境是xp,mysql版本5....
c 預處理和預處理命令
預處理發生在編譯之前,預處理輸出的是乙個單一的檔案,這個檔案被送到編譯器,進行編譯。每條預處理命令都控制預處理器的行為。每條預處理命令佔據一行,有以下的格式 character 預處理命令 one of define,undef,include,if,ifdef,ifndef,else,elif,e...
mysql 預處理語句 in MySQL預處理語句
預製語句的sql語法基於三個sql語句 prepare stmt name from preparable stmt execute stmt name using var name var name prepare stmt name prepare語句用於預備乙個語句,並賦予它名稱stmt na...