HP層到MySQL層
Php到sql元件層次如下圖所示:
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引擎將透過mysql(mysqlnd和libmysql)查詢引擎向MySQL伺服器發出查詢請求。
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。
服務端快取模式
客戶端命令: mysql_unbuffer_query(),在客戶端的sql驅動擴展(mysqlnd)中不設定結果集的緩存,所以在fecth_array_xxx從結果集中讀取一條記錄時,需要xxx從服務端的緩衝區讀取。
服務端無快取模式
客戶端指令: 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。
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_MACHINESOFTWAREMicrosoftWindows CurrentVersion ExplorerMyComputerNameSpaceDelegateFolders,把{59031a47-3f72-44a7-89c5-5595fe230的電腦,這些煩人的資料夾就不存在了。
以上就介紹了PHP到MySQL資料查詢流程概述,包括了方面的內容,希望對PHP教學有興趣的朋友有幫助。