一:背景 1. 講故事 上一篇寫完 SQLSERVER 的四個事務隔離級別到底怎麼理解? 之後,有朋友留言問什麼時候可以把 snapshot 隔離級別給補上,這篇就來安排,快照隔離級別看起來很魔法,不過在修車之前,得先看下怎麼開車。 二:snapshot 隔離詳解 1. snapshot 之前的困境 ...
前置知識
Using filesort:表示需要用到 sort buffer 記憶體空間進行排序
sort buffer 是一塊可調整的記憶體空間,如果需要排序的數據量太大而空間不夠,將用到磁碟臨時文件來排序,效率很低
什麼情況下會用到 sort buffer 來排序?
不能根據索引直接知道排序結果,就需要用到 sort buffer
排序的執行情況?
表T:id (primary key), city (key), name, age 等欄位
explain select city,name,age from T where city = 'gz' order by name;
-- 走了索引(但是是非覆蓋索引),需要排序,需要進行回表查詢
-- Using index condition; Using filesort
這個 SQL語句可以知道,不能根據索引直接知道排序結果,所以需用到 sort buffer 排序
● 全欄位排序 執行流程
初始化 sort buffer,確定此記憶體中需要存放的欄位
到 city 欄位索引上找到匹配的第一行
回表查詢,把 city,name,age 存到 sort buffer 中
重覆上述兩步,直到不滿足 where 條件(city 索引上找到一行不滿足的數據)
對 sort buffer 中的數據排序
返回結果集給客戶端
● rowid 排序執行流程
排序前,會檢測放入 sort buffer 中的欄位的長度,如果超過最大單行長度值(可調),那麼就會只放rowid 和 需要排序的欄位
explain select city,name,age from T where city = 'gz' order by name;
-- 走了索引(但是是非覆蓋索引),需要排序,需要進行回表查詢
-- Using index condition; Using filesort
MySQL如果檢測到 city,name,age 等欄位超過了最大單行長度值,就會只把 id, name 等欄位放入 sort buffer 中
執行流程
相比全欄位排序,基本流程一致。存入 sort buffer 中的欄位變少了,在排序完後,又要回表查詢然後返回結果集。效率變低了
這個排序機制是為了保證儘可能的使用 sort buffer 記憶體排序,減少記憶體存放的數據行,那麼存放的數據量就更多。從而降低/不適用磁碟臨時文件排序
如何優化?
可以這樣創建普通索引 (city, name)。那麼執行上述 SQL 語句時,不會用到記憶體排序
執行流程
到 city 欄位索引上找到匹配的第一行
回表查詢,把 city,name,age 作為 結果集 的一部分直接返回
重覆上述兩步,直到不滿足 where 條件