程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> PHP到MySQL數據查詢過程概述

PHP到MySQL數據查詢過程概述

編輯:關於PHP編程

PHP到MySQL數據查詢過程概述


HP層到MySQL層

Php到sql組件層次如下圖所示:

PHP到MySQL數據查詢過程概述

ext/mysqli和ext/mysql 是客戶端的擴展程序庫(庫函數) ,在客戶端腳本層面的擴展庫。 Mysqli庫是mysql庫的擴展版本,擴展版本增加了列版定Bind Column)綁定。PDO (PHP Data Object) 是另外一種面向數據對象的 擴展庫。這些擴展庫直接面向編程者,而它的底層實現是mysql連接引擎如mysqlnd和libmysql )參考 http://bbs.chinaunix.net/thread-3679393-1-1.html 、http://blog.csdn.net/treesky/article/details/7286098 )。

mysqlnd和libmysql 是PHP端客戶端)的數據庫連接驅動引擎。libmysql 是通用的數據庫連接引擎,而mysqlnd是專屬PHP開發的連接引擎,從屬於Zend中。 當PHP通過調用擴展庫ext/mysqli和ext/mysql)中的mysql_query() 函數進行數據庫查詢的時候,Zend引擎將通過mysqlmysqlnd和libmysql)查詢引擎向MySQL服務器發出查詢請求。

MySQL層的數據查詢

PHP到MySQL數據查詢過程概述

MySQL服務器接受到客戶端的查詢請求後,查詢執行過程如上圖所示:
1. 查詢緩存,如果命中則直接將結果集返回給到客戶端,否則進入步驟2
2. 對SQL語句依次進行解析、預處理、查詢優化等操作,最終生成查詢執行計劃select的查詢執行計劃可以通過explain select 查看)
3. MySQL服務端的查詢執行引擎將依據查詢執行計劃 調用存儲引擎對數據進行查詢。當SQL語句的最後一層關聯被執行後,將產生查詢結果集
4. 查詢結果集發送到客戶端,傳回的方式有兩種:MySQL服務端緩存結果集 或 不緩存,這個由參數SQL_BUFFER_RESULT設置。 並且,如果用戶設置了SQL_CACHE 那麼本次的查詢的結果集的一份副本存儲於 查詢緩存 中步驟1相關)。

SQL_CACHE參數的啟示:
將復雜的多個關聯)查詢分解為多條簡單的查詢,因為
1)簡單查詢的緩存命中搞、
2)復雜查詢結果的緩存易失效關聯太多表)
3)簡單查詢鎖的持有率低

MySQL Server 到 PHP層

通信模式MySQL Server和客戶端的通信采用“半雙工通信”,意思是:客戶端和服務端只能有一個在讀,並且另外一個必須是寫。

優點:協議簡單,客戶端和服務端的寫權限是互斥的

缺點:無法進行流量控制,一端開始發送消息,另一端要完整的接受這個消息後才能響應它。

啟示:服務端查詢後的結果集發送給客戶端,客戶端客戶端的查詢引擎,例如mysqlnd)必須完整的接受。所以,如果只需要少數行,記得在sql語句添加使用limit,少用select *。

結果集回傳模式結果集回傳中,每一行記錄都通過 客戶端-服務器通信協議進行包裝,然後再交接給下層的tcp協議;當然,在tcp層,可以先緩存每行記錄的協議包,組成大包在發出對應用層透明)。

MySQL服務端只有將結果集全部發送給客戶端後,才能釋放結果集所占用的buffer。

服務端緩存模式

PHP到MySQL數據查詢過程概述


客戶端命令: mysql_unbuffer_query(),在客戶端的sql驅動擴展mysqlnd)中不設置結果集的緩存,所以在fecth_array_xxx從結果集中讀取一條記錄時,需要從服務端的緩沖區中讀取。

服務端無緩存模式

PHP到MySQL數據查詢過程概述


客戶端命令: mysql_query(),在客戶端的sql驅動擴展mysqlnd)中設置了buffer用於緩存服務端的結果集,所以在fecth_array_xxx從結果集中讀取一條記錄時,是直接從mysqlnd擴展的緩沖區中取得row。

小結

如果結果集很大: 服務端無緩存模式可以減少服務端的內存壓力喲,但是占用客戶端的內存。這樣只有看情況取捨了。

PHP層到用戶層

在客戶端,於服務端對接的是mysql擴展引擎libmysql 或者 mysqlnd),而用戶層是通過擴展庫ext/mysql 或 ext/mysqli)和mysql引擎進行交互啟示就是調用引擎的api讀取結果集)。

引 擎libmysql 和 mysqlnd 的機制並不同,主要區別是mysqlnd是轉為php寫的,被編譯到zend內部。而libmysql是通用的庫,zend需要調用該庫實現數據庫的連 接。在這種卻別下,mysqlnd和zend具有更好的粘合性,在數據傳輸到用戶層時,少了一層數據的拷貝。具體的架構區別如下圖所示。圖中,五角星表示 緩存 buffer。


PHP到MySQL數據查詢過程概述


ext/mysqli和ext/mysql 是客戶端的擴展程序庫(庫函數) : 在客戶端腳本層面mysqlInd和libmysql 是MySQL Server端的驅動程序。其中,libmysql是通用的MySQL查詢驅動程序,而mysqlnd是專為PHP設置的基於Zend引擎的SQL驅動,即mysqlnd的數據驅動動作需要經過Zend和mysqlserver交互,而libmysql直接和mysqlserver交互的。

對比:
ext/mysqli或者ext/mysql)和libmysql的數據庫查詢中的過程為:
1)mysqi向libmysql驅動發送查詢請求
2)Libmysql執行請求並得到結果集存儲域libmysql的buffers中
3)Mysqli申請內存:zval指定的一塊buffer
4)Mysqii從libmysql拷貝結果集到zval指定的buffer中
ext/mysqli或者ext/mysql)和mysqlnd的數據庫查詢中的過程為:
1) mysqi向mysqlnd驅動發送查詢請求
2) mysqlnd驅動通過zend引擎執行sql查詢,結果集的每一行由一個buffer存儲各個buffer是分散的)
3) Mysqlnd創建多個zval,並指向這些buffers

例如:
在ext/mysql & libmysql 中,libmysql驅動執行SQL語句後得到結果集Row1~Row3,然後ext/mysql將結果集拷貝到zend buffer中,之後mysqli_fetch_xxx函數從該區域內存中讀取結果集中的內容。
在ext/mysqli & mysqlInd 中,mysqlnd 驅動執行SQL語句得到結果集Row1~Row3,其中,每個row直接由zend的一個buffer存儲,並由一個zval指向。客戶端通過映射直接從 該內存區域中讀取結果實現mysqli_fetch_xxx。

小結

mysqlnd和zend更具有粘合性,在sql查詢驅動中,mysqlnd通過zend引擎訪問數據庫,並直接將將結果存儲域zend的buffer中,相比libmysql驅動獨立於zend),少了一次結果集緩存拷貝。

參考

《高性能MySQL》

http://www.cnxct.com/libmysql-mysqlnd-which-is-best-and-what-about-mysqli-pdomysql-mysql/

http://www.cnxct.com/wp-content/uploads/2012/12/andrey-mysqlnd.pdf

版權聲明:本文為博主http://blog.csdn.net/ordeder)原創文章,未經博主允許不得轉載。

以上就介紹了PHP到MySQL數據查詢過程概述,包括了方面的內容,希望對MySql有興趣的朋友有所幫助。

 

電腦/手機小常識:取消共享文檔
默認情況下,在Windows XP中打開我的電腦,會看到在硬盤圖標上方有一些文件夾。這些就是“共享文件夾”,這裡有每一個用來戶共享文件所用的文件夾。我們可以讓這些文件夾在我的 電腦中消失,原理很簡單,只要打開注冊表找到如下位置:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows \CurrentVersion\ Explorer\MyComputer\NameSpace\DelegateFolders,把 {59031a47-3f72-44a7-89c5-5595fe6b30ee}鍵值刪掉,下次打開我的電腦,這些煩人的文件夾就不復存在了。

     



  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved