天天看點

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引擎将通過mysql(mysqlnd和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)簡單查詢鎖的持有率低

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

啟示:服務端查詢後的結果集發送給用戶端,用戶端(用戶端的查詢引擎,例如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)和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。

參考

《高性能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有興趣的朋友有所幫助。

<b>電腦/手機小常識:</b>取消共享文檔

預設情況下,在windows

xp中打開我的電腦,會看到在硬碟圖示上方有一些檔案夾。這些就是“共享檔案夾”,這裡有每一個用來戶共享檔案所用的檔案夾。我們可以讓這些檔案夾在我的

電腦中消失,原理很簡單,隻要打開系統資料庫找到如下位置:hkey_local_machine\software\microsoft\windows

\currentversion\ explorer\mycomputer\namespace\delegatefolders,把

{59031a47-3f72-44a7-89c5-5595fe6b30ee}鍵值删掉,下次打開我的電腦,這些煩人的檔案夾就不複存在了。

來源:51cto