一次MySQL查詢的大致過程

2021-08-29 20:40:16 字數 1591 閱讀 1883

如果想盡可能地優化 mysql 的效能,那麼必須對 mysql 查詢的全過程有個大體上的了解,為後續的優化工作打下基礎。

第一步:傳送 sql 語句

客戶端與 mysql 伺服器建立 tcp 連線後傳送一條 sql 語句給 mysql 伺服器。

客戶端和 mysql 伺服器之間的通訊協議(應用層協議)是「半雙工」的,因此,同乙個時刻,只能有一方在傳送資料,同時,另一方要麼完整地接受資料,要麼粗暴地斷開連線。

第二步:檢查查詢快取

mysql 伺服器會先檢查 sql 語句是不是 select 型,如果是,則會先去檢查查詢快取,如果快取命中,則立即返回儲存在快取中的結果。如果未命中,則執行下一步。(可以通過配置來關閉查詢快取)

第三步:生成執行計畫

mysql 伺服器進行 sql 解析、預處理,最後,優化器會先**多個執行計畫的成本,然後選擇生成其中成本最小的乙個。優化器根據一系列的統計資訊得來:每個表或者索引的頁數(page)、索引的基數(即索引中不同值的數量)、索引和資料行的長度、索引分布情況等,注意優化器並沒有考慮到任何快取,它假設所有讀取都是讀磁碟。

注意,解析和預處理的主要作用是檢測 sql語句是否有錯誤,而這裡的執行計畫是一顆「指令樹」。

儲存引擎將資料返回給 mysql 伺服器後(一條一條),還有可能對返回的資料進行篩選、排序、分組等操作。

第五步:返回結果

mysql 伺服器將結果返回給客戶端,這是乙個增量、逐步返回的過程,伺服器一旦得到了一條完整的記錄,就開始向客戶端逐步返回結果集了。也就是說,結果集中的每一行都會以 mysql 客戶端 / 伺服器通訊協議進行封包,然後再通過 tcp協議傳輸。

這種做法的好處是,mysql 不需要儲存太多的結果,節約了記憶體,同時,也能讓客戶端盡早地接收到結果。

可以通過使用 sql_buffer_result 來改變 mysql 的這種行為,這個 hint 告訴優化器將查詢結果先放入到乙個臨時表中,然後盡快地釋放相關的鎖資源。不過,帶來的壞處是 mysql伺服器將需要更多的記憶體。

另外,多數連線 mysql 的庫函式(比如,php 中的 pdo),預設情況下,都是先將全部結果集快取在記憶體中。

//  省略資料庫連線部分

$stmt = $pdo->query("select * from address");

while ($obj = $stmt->fetchobject()) 12

345當執行到 while 時,pdo 就已經將整個結果集快取到記憶體中了,while 迴圈只是從應用快取中逐行取出資料。

預設的這種行為的好處在於 mysql 能盡快地完成這次查詢,盡快釋放相關資源。壞處在於花費了時間和記憶體來儲存整個結果集,當結果集很大的時候,可能發生超出記憶體的現象。

可以更改 pdo的這種預設行為:

$pdo->setattribute(\pdo::mysql_attr_use_buffered_query, false);

$stmt = $pdo->query("select * from address");

while ($obj = $stmt->fetchobject()) 12

345此後,pdo 將不會快取結果集了,而是每次迴圈都從 mysql伺服器取回一條資料。這種做法會延遲了伺服器釋放各種資源比如鎖、連線的時間。

首頁查詢功能的一次實現過程

本次的目的是完成學生選課系統的首頁查詢功能的實現,1.在首頁顯示當前周的課表。2.顯示所有的學生每節課的有無情況。1.查詢當前學期的所有課程 2.查詢本週,週幾,第幾節課的課程id 3.通過課程id查詢有那些學生選擇了該課程 4.將查詢到的學生id設為有課,其餘為無課,並將資料傳輸到v層 依照以上方...

記一次 OOM 查詢過程

監控系統發現服務掛掉,登上機器ps ef grep 發現程序還在,因為監控系統是通過心跳檢測來監控服務的存活狀態的,服務假死 1 df free top 三連 磁碟空間正常 記憶體使用率正常 某個程序的cpu佔用率達300 多 2 top h p pid 檢視占用cpu最高的程序對應執行緒,得到執行...

記錄一次查詢調優過程

調優過程中使用explain命令檢視執行過程,包括執行時間 掃瞄方式 是否用到索引等,explain 使用 timing on timing off 乙個查詢介面被頻繁呼叫,且查詢過程較慢 首先考慮優化sql語句 其次考慮優化業務 最後考慮是否需要新增快取機制 3.1 優化sql 原始sql,分組查...