# [更新] `5.1.25`查詢參數綁定的改進
>[danger] `V5.1.25`版本已經發布了,該版本主要對查詢的參數綁定做了一些優化和改進,本文略為講解下一些改進的細節以及注意事項。
## 自動參數綁定
可能很多開發者在使用`ThinkPHP`的時候并沒有特別注意到查詢參數綁定,因為幾乎所有的查詢都是自動參數綁定的。例如,下面是一個很普通的查詢:
```
Db::name('user')->where('id', 10)->find();
```
拋開如何把查詢構造器語法解析為最終的SQL,實際在執行最終的解析SQL的時候會先經過下面的三個步驟。
```
// 預處理
$PDOStatement = $PDO->prepare('SELECT * FROM user WHERE id = :id');
// 參數綁定
$PDOStatement->bindValue('id', 10, PDO::PARAM_INT);
// 執行SQL查詢
$PDOStatement->execute();
```
而自動參數綁定其實是在解析最終SQL的時候處理完成的,也就是把`id`的實際值使用`:id`占位符處理,然后在綁定數據中進行命名占位符的綁定對應,最終交由`bindValue`方法統一處理。
因此,基本上你不需要關注參數綁定的存在,也不需要進行手動參數綁定,只有在少數原生查詢或者字符串條件的情況下,才需要手動進行參數綁定,一般來說有下面兩種參數綁定方式。
```
// 使用?占位符綁定
Db::query("select * from think_user where id=? AND status=?", [8, 1]);
Db::name('user')
->where('where id=? AND status=?', [8,1])
->select();
// 使用命名占位符綁定
Db::name('user')
->where('where id=:id AND status=:status', ['id' => 8, 'status' => 1])
->select();
Db::execute("update think_user set name=:name where status=:status", ['name' => 'thinkphp', 'status' => 1]);
```
>[danger] 除了上述的手動綁定方式外,`Query`類還提供了一個`bind`方法用于指定查詢的參數綁定,但并不建議使用,因為使用查詢表達式查詢的數據都會進行自動參數綁定,這個情況下進行手動綁定是多余的,對性能也不會有任何的提升。
## 性能優化
因為`5.1`版本一直以來為了直觀,采用的都是命名(占位符)的綁定方式,但由于命名綁定的方式需要檢測是否存在相同的命名,以及做出避免沖突的處理,從而帶來了一定的性能開銷,這個性能開銷在你的數據量特別大的情況下(例如`insertAll`了大量的數據)會變得非常明顯,而真正開銷最大的地方其實是在每次獲取實際的查詢SQL都會進行命名綁定的參數替換。
>[info] 出于性能的優化考慮,`5.1.25`版本開始底層改為`?`占位符處理查詢參數綁定,但并不影響你在**使用原生查詢**的時候使用命名占位符綁定。
此次改進后,對于大量數據的查詢性能會有明顯的提升。之前版本如果使用`insertAll()`方法批量寫入1000條數據的性能開銷在`3s`左右(這是一個幾乎奔潰的性能),性能甚至遠遠不如模型類的`saveAll()`方法大約`0.04s`(因為`saveAll`方法是每次寫入一條數據)。改進后使用`insertAll()`方法批量寫入1000條數據的性能開銷在`0.03s`左右,性能略好于模型類的`saveAll()`方法大約`0.04s`,效果還是比較顯著的。
如果你不幸暫時沒有辦法升級到`5.1.25`版本以上,那么建議你在使用`insertAll`方法批量寫入大數據的時候,改為下面的方式。
```
// 多次寫入,每次寫入100條
Db::name('user')->limit(100)->insertAll($data);
```
那么有什么注意事項呢?我們知道,PDO的參數綁定是不支持`?`占位符和命名占位符混合使用的。當你在查詢構造器中使用了命名占位符的話,系統會自動轉化為`?`占位符的方式,包括下面幾種情況。
```
// 使用命名占位符綁定 系統會自動轉換為?占位符方式
// 因此必須確保你的變量綁定順序和占位符順序一致
// 正確
Db::name('user')
->where('where id=:id AND status=:status', ['id' => 8, 'status' => 1])
->select();
// 正確
Db::name('user')
->where('where id=? AND status=?', [ 8, 1])
->select();
// 正確但不建議使用
Db::name('user')
->where('where id=:id AND status=?', ['id' => 8, 1])
->select();
// 錯誤
Db::name('user')
->where('where id=:id AND status=:status', [ 'status' => 1, 'id' => 8])
->select();
```
另外,查詢構造器的`whereExp`和`whereRaw`方法中的參數綁定也會進行自動轉換。
```
Db::name('user')
->whereRaw('where id=:id AND status=:status', ['id' => 8, 'status' => 1])
->select();
```
但原生查詢則不做任何轉換(只要你使用統一的占位符方式即可),因此下面的手動參數綁定不做任何處理,并且依然有效。
```
// 使用?占位符綁定
Db::query("select * from think_user where id=? AND status=?", [8, 1]);
// 使用命名占位符綁定
Db::execute("update think_user set name=:name where status=:status", ['name' => 'thinkphp', 'status' => 1]);
```
>[danger] 最后,再次強調,不要手動使用`bind`方法進行參數綁定,沒有必要,而且會導致不可預知的問題。
## 浮點型支持
PDO參數綁定對浮點型并沒有做特殊的支持,尤其是在PHP`7.2+`版本開始,對`PDO::PARAM_INT`綁定類型更為嚴格后,導致浮點型會被自動處理為整數。
為了更好的支持浮點型的參數綁定,ThinkPHP`5.1.25`版本引入了一個內置常量`Connection::PARAM_FLOAT`作為內部自動參數綁定的綁定類型,自動對浮點型的數據內部按照`PDO::PARAM_STR`進行參數綁定,但在生成SQL語句的時候仍然按照浮點型數據進行處理。
- 值得升級到5.1的18個理由
- 5.1.7版本新特性
- JSON字段類型在ORM中的使用
- 文件下載響應對象
- 教你使用5.1的數組對象查詢
- 模型三大利器之一:搜索器
- 在ThinkPHP中使用Yaconf
- 掌握命令行的表格輸出
- 5.1.25查詢參數綁定的改進
- ThinkPHP安全規范指引
- 巧用數據集的排序功能實現統計排序
- think-orm ——基于5.1的獨立ORM庫
- think-template——基于ThinkPHP的獨立模板引擎
- ThinkPHP5.1.26版本發布——修正版本,包含安全更新
- ThinkPHP5.0和3.2再發安全更新
- 官宣:ThinkPHP發布首個LTS版本
- 你真的了解Db類和模型的正確使用姿勢么?
- 如何更有效的記錄和管理日志
- 模型三大利器之二:修改器
- ThinkPHP5.1.28版本發布——修正上一版本問題,改進關聯查詢
- 模型三大利器之三:獲取器
- API版本控制的幾種思路
- ThinkPHP5.2第一個Beta版本發布測試
- 讓你少犯錯的數據查詢基本原則
- ThinkPHP發布5.1.29版本——常規更新
- 這15個好習慣讓你更容易升級到5.2
- 如何有效提高ThinkPHP的應用性能
- 讓你提高開發效率的查詢技巧
- 模型關聯查詢不完全指南
- 5.2發布Beta2版本——統一和精簡大量用法
- ThinkPHP發布5.1.30版本——支持微秒時間字段寫入
- ThinkPHP的數據緩存使用
- ThinkPHP5.2安裝及入口文件
- ThinkPHP榮獲2018 年度最受歡迎中國開源開發框架第1名
- 5.1路由使用心得技巧
- ThinkPHP5.*版本發布安全更新
- ThinkPHP項目及代碼規范指北
- 5.2版本的設計規范指導
- ThinkPHP5.1.32版本發布——圣誕快樂
- 利用Trait特性給模型增加樂觀鎖功能
- 5.2數據庫和模型的變化(摘要)
- ThinkPHP模板引擎實現和常見問題
- ThinkPHP5.0.24版本發布——安全更新
- 不忘初心,方得始終——ThinkPHP十三周年報告
- ThinkPHP5+相關資源匯總
- 異步社區ThinkPHP周年慶專享優惠活動
- 5.2路由的調整和改進
- ThinkPHP發布5.1.33版本——包含安全更新
- ThinkPHP擴展開發指南
- ThinkPHP發布5.2Beta3版本
- ThinkPHP發布5.1.34版本——喜迎新年
- ThinkPHP發布5.2RC1版本
- ThinkPHP發布5.1.35版本——常規更新
- 5.2配置類的調整
- 5.2時間查詢的改進和優化
- 5.2RC版本升級不完全指導(僅供學習參考)
- ThinkPHP5.2版本正式變更為6.0版本
- ThinkPHP百度云云虛擬主機專享免費活動
- 事件系統以及查詢事件、模型事件的使用
- ThinkPHP6.0RC2版本發布——架構升級、精簡核心
- ThinkPHP5.1.36LTS版本發布——常規更新
- 新版Session和Cookie設計變化
- ThinkPHP5.1.37版本發布——常規更新
- ThinkPHP6.0RC3版本發布——細節完善,體驗優化
- 6.0中間件使用詳解
- Composer各大廠商鏡像地址
- ThinkPHP6.0發布計劃公告
- 「ThinkPHP開發者周刊」招募志愿者
- ThinkPHP6.0日志變化
- ThinkPHP5.1.38版本發布——常規更新
- ThinkPHP6.0RC4版本發布——ORM獨立,日志多通道支持
- ThinkORM2.0開發指南上線
- ThinkPHP6.0RC5版本發布——多應用模式獨立,中間件機制調整
- ThinkPHP6.0版本發布——程序員節福利
- ThinkPHP5.1.39LTS版本發布——常規更新
- ThinkPHP6.0.1版本發布——圣誕快樂!
- 回顧2019,展望2020!
- ThinkPHPV6.0.2版本發布——2020新春快樂!
- 周年福利系列:Swoole合作優惠
- 億速云成為ThinkPHPV6.0獨家贊助發布商??
- 新冠疫情工具和限免資源專題(保持更新中)
- 周年福利系列:創宇信用認證合作優惠
- 周年福利系列:碼云企業版限時10%優惠
- 周年福利系列:想天短說抵現優惠
- think-swoole直播:從零開始掌握swoole開發
- 周年福利系列:B2C開源電商ShopXO授權8折優惠
- 周年福利系列:LayuiAdmin 永久授權限時優惠
- ThinkPHP資源導航站上線——構建生態 服務未來
- ThinkPHP官方技術支持服務和應用服務市場上線公測
- ThinkPHP市場精選——推廣基本要素
- ThinkPHP市場精選——客服聊天專題
- ThinkPHPV6.0.3版本發布——端午安康
- ThinkPHP開發者扶持計劃
- 6.0.3版本關鍵更新及升級事項
- 「ThinkPHP開發者周刊」改版重啟
- ThinkPHP市場精選——企業建站專題
- ThinkPHP 提供統一API接口服務
- ThinkPHP市場精選——直播電商專題
- ThinkAPI服務SDK發布
- 官方服務市場啟用獨立子域名
- ThinkPHP市場精選——刷臉支付專題
- ThinkAPI推出會員服務計劃
- ThinkPHPV6.0.4版本發布——中秋國慶雙節快樂
- ThinkPHPV5.1.40版本發布——常規更新
- 1024程序員節福利走一波
- ThinkPHP V6.0.5版本發布——兼容Composer2.0
- 知識圖譜應用場景——源論技術沙龍
- ThinkPHP5.*版本改進Composer2.0的兼容
- 官方市場雙十一精選推薦
- 技術人做產品有機會么(文末送課程)
- 本周秒殺——古德云售后獲客營銷系統
- ThinkAPI服務更新——支持接口分組和PHP版本依賴調整
- PHP8新特性盤點
- PHP8新特性系列:構造器屬性提升使用及注意事項
- ThinkPHP2021新年寄語
- ThinkPHP V6.0.6&V5.1.41版本發布——兼容PHP8.0
- PHP如何更優雅地調用API接口
- ThinkPHP V6.0.7發布——修正版本
- ThinkAPI服務更新——IP白名單
- 最新版ThinkORM對于時間字段的調整
- ThinkAPI短信接口正式上線
- ThinkPHP V6.0.8版本發布——多環境變量配置支持
- 頂想云寫作服務開啟第一次公測
- ThinkSSL上線——官方SSL/TLS證書服務
- MDBootstrap國內用戶福利——ThinkPHP官方市場首發
- ThinkPHP V6.0.9版本發布——常規更新
- ThinkORM功能盤點——虛擬模型
- 全面支持主流GIT版本庫——云寫作服務第二次公測
- 云寫作服務私有化部署方案之:版本庫私有化
- 看云雙十一活動
- ThinkPHP V6.0.10LTS發布——兼容PHP8.1
- ThinkPHP V6.0.12發布——命令行兼容8.1
- 頂想云知識管理上線公測——構建企業文檔中心和知識庫
- 頂想云上線——助力生態數字化建設
- 618活動進行中——官方市場迎來一波更新
- 頂想云知識管理正式上線——看云文檔啟動遷移服務
- ThinkPHP V6.0.13發布——常規更新
- 頂想云網站助理服務上線——構建產品支持服務
- ThinkPHP發布6.1.0&6.0.14版本——安全更新
- ThinkPHP新版社區上線試運營
- ThinkAPI上架人臉核身接口——助力網站實名認證
- 辭舊迎新——舊版社區停止注冊及發帖
- ThinkPHP6.1.2版本發布——兼容PHP8.2