標籤:

PDO->prepare() bind vs sprintf() difference in performance

最近在做與資料庫有關的東西, 為了使 SQL 語句美觀可讀, 所以希望將語句與變數分開寫, 而不是直接拼成一個字元串.

PHP 里有兩種比較簡單的實現方法: 用 PDO 或其它類庫提供的預處理函數綁定變數; 或者用格式化字元串的函數 vsprintf() / sprintf() 處理.

本來想 Google 一下二者的性能差異, 結果 Stack Overflow 上居然沒人討論過, 於是自己測試了一下.

1.

$sql = new PDO(mysql:balabala);nn$state = ;n$param = [];nfor($i = 0; $i < 30000; ++ $i) {n $state .= n INSERT tablen SET table.`column_1` = ?,n table.`column_2` = ?n ;;n $param = array_merge($param, [n value_1,n value_2,n ]);n}nn$sql->prepare($state)->execute($param);n

將 30000 條有待格式化的語句拼接成一個字元串, 並將這些語句所需的變數存進一個一維數組, 最後通過 prepare()->execute() 綁定變數並查詢. 用時如下:

15.692095994949n15.630060911179n15.150625944138n16.030143976212n15.356143951416n18.03054189682n17.217720985413n17.266310930252n16.444499015808n17.730359077454n

2.

$sql = new PDO(mysql:balabala);nn$state = ;n$param = [];nfor($i = 0; $i < 30000; ++ $i) {n $state .= n INSERT tablen SET table.`column_1` = "%s",n table.`column_2` = "%s"n ;;n $param = array_merge($param, [n value_1,n value_2,n ]);n}nn$sql->query(vsprintf($state, $param));n

過程與第一種一致, 區別在於最後使用 vsprintf() 格式化字元串, 再通過 query() 查詢.

17.125224113464n16.484893083572n16.754585981369n17.174664974213n16.763854026794n17.275769948959n16.80862402916n18.309125900269n17.161306858063n17.066431045532n

速度貌似比第一種慢了一丟丟, 不過差別不大.

3.

$sql = new PDO(mysql:balabala);nn$state = ;nfor($i = 0; $i < 30000; ++ $i) {n $state .= vsprintf(n INSERT tablen SET table.`column_1` = "%s",n table.`column_2` = "%s"n ;, [n value_1,n value_2,n ]);n}nn$sql->query($state);n

再試一下每次循環通過 vsprintf() 直接格式化字元串, 不再最後處理, 最後只通過 query() 查詢.

8.2746200561523n8.7131369113922n8.0337510108948n7.258749961853n7.058333158493n8.8596909046173n7.7941257953644n7.8908619880676n9.0065298080444n7.5366899967194n

速度直接快了一倍.

4.

$sql = new PDO(mysql:balabala);nn$state = ;nfor($i = 0; $i < 30000; ++ $i) {n $state .= sprintf(n INSERT tablen SET table.`column_1` = "%s",n table.`column_2` = "%s"n ;,n value_1,n value_2n );n}nn$sql->query($state);n

最後順便試一下在第三種的基礎上, 將 vsprintf() 換成 sprintf().

7.0037219524384n7.651113986969n7.4348628520966n7.3054690361023n10.954452037811n7.9271950721741n7.2161939144135n7.6246650218964n6.8968040943146n7.2924418449402n

速度貌似微妙地快了一丟丟.

所以綜合來看, 將語句先格式化好再拼起來, 比攢成一堆再格式化要快不少, 如果非要攢成一堆再格式化, 使用 PDO->prepare() 可能比 vsprintf() 快一點點 (然而這是什麼鬼需求).

推薦閱讀:

教你怎麼用EXCEL練習SQL
SQL 設計得爛嗎,諸如redis,nosql又該如何選擇?
Sqli labs系列-less-5&6 報錯注入法(下)
sql中為什麼select要放在from之前?
win7如何安裝SQL資料庫2000?

TAG:PHP | 编程 | SQL |