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)簡單查詢鎖的持有率低
優點:協定簡單,用戶端和服務端的寫權限是互斥的
啟示:服務端查詢後的結果集發送給用戶端,用戶端(用戶端的查詢引擎,例如mysqlnd)必須完整的接受。是以,如果隻需要少數行,記得在sql語句添加使用limit,少用select *。
結果集回傳模式結果集回傳中,每一行記錄都通過 用戶端-伺服器通信協定進行包裝,然後再交接給下層的tcp協定;當然,在tcp層,可以先緩存每行記錄的協定包,組成大包在發出(對應用層透明)。
mysql服務端隻有将結果集全部發送給用戶端後,才能釋放結果集所占用的buffer。
服務端緩存模式
用戶端指令: mysql_unbuffer_query(),在用戶端的sql驅動擴充(mysqlnd)中不設定結果集的緩存,是以在fecth_array_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)和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