1. 書寫順序
select->distinct->from->join->on->where->group by->having->order by->limit
必須字段:select、from
可選字段:distinct、join、on、where、group by、having、sum、count、max、avg、order by、limit
2. 執行順序
from->on->join->where->group by->sum、count、max、avg->having->select->distinct->order by->limit
# 用左連接配接的方式查詢 bumen 表和 yuangong 表。使用 LEFT JOINON 來實作左連接配接。
select bumen.d_id,d_name,function,bumen.address,id,name,birthday,sex,salary,yuangong.address
from bumen
left join yuangong
on yuangong.d_id=bumen.d_id;
bumen表與yuangong表進行笛卡爾積運算,根據yuangong.d_id=bumen.d_id篩選出符合條件的行,再根據這是左連接配接, left join一般以左表為驅動表,然後用此表的記錄去關聯其他表,即使其他表對應元組為空,最後執行select操作,選擇出指定的列
FORM: 對FROM的左表和右表計算笛卡爾積。産生虛表VT1
ON: 對虛表VT1進行ON篩選,隻有那些符合的行才會被記錄在虛表VT2中。
JOIN: 如果指定了OUTER JOIN(比如left join、 right join),那麼保留表中未比對的行就會作為外部行添加到虛拟表VT2中,産生虛拟表VT3, 如果 from 子句中包含兩個以上的表的話,那麼就會對上一個join連接配接産生的結果VT3和下一個表重複執行步驟1~3這三個步驟,一直到處理完所有的表為止。
WHERE: 對虛拟表VT3進行WHERE條件過濾。隻有符合的記錄才會被插入到虛拟表VT4中。
GROUP BY: 根據group by子句中的列,對VT4中的記錄進行分組操作,産生VT5.
CUBE | ROLLUP: 對表VT5進行cube或者rollup操作,産生表VT6
HAVING: 對虛拟表VT6,即已經分組的資料進行過濾的條件,隻有符合的記錄才會被 插入到虛拟表VT7中
SELECT: 執行select操作,選擇指定的列,插入到虛拟表VT8中
DISTINCT: 對VT8中的記錄進行去重。産生虛拟表VT9
ORDER BY: 将虛拟表VT9中的記錄按照進行排序操作,産生虛拟表VT10
LIMIT:取出指定行的記錄,産生虛拟表VT11, 并将結果傳回。
3. 關鍵詞含義
- from:需要從哪個資料表檢索資料
- join:對需要關聯查詢的表進行關聯關聯查詢時,資料庫會選擇一個驅動表,然後用此表的記錄去關聯其他表 left join一般以左表為驅動表(right join一般為右表),inner join一般以結果集少的表為驅動表,left join某些情況下會被查詢優化器優化為inner join
-
- 驅動表選擇原則:在對最終結果集沒影響的前提下,優先選擇結果集最少的那張表作為驅動表
- 在使用索引關聯的情況下,有
和Index Nested-Loop join
兩種算法Batched Key Access join
- 在未使用索引關聯的情況下,有
Simple Nested-Loop join
Block Nested-Loop join
-
(SNLJ,簡單嵌套循環連接配接)算法:根據on條件,從驅動表取一條資料,然後全表掃面被驅動表,将符合條件的記錄放入最終結果集中。這樣驅動表的每條記錄都伴随着被驅動表的一次全表掃描Simple Nested-Loop join
-
-
- 比對次數:外層表行數*内層表行數
-
-
-
(INLJ,索引嵌套循環連接配接)算法:索引嵌套循環連接配接是基于索引進行連接配接的算法,索引是基于内層表的,通過外層表比對條件直接與内層表索引進行比對,避免和内層表的每條記錄進行比較, 進而利用索引的查詢減少了對内層表的比對次數Index Nested-Loop Join
-
-
-
- 比對次數:外層表行數*内層表索引高度
-
-
-
(BNLJ,緩存塊嵌套循環連接配接)算法:緩存塊嵌套循環連接配接通過一次性緩存多條資料,把參與查詢的列緩存到Join Buffer 裡,然後拿join buffer裡的資料批量與内層表的資料進行比對,進而減少了内層循環的次數(周遊一次内層表就可以批量比對一次Join Buffer裡面的外層表資料)。當不使用Block Nested-Loop Join
的時候,預設使用Index Nested-Loop Join
Block Nested-Loop Join
-
(BKAJ)算法:和SNLJ算法類似,但用于被join表上有索引可以利用,那麼在行送出給被join的表之前,對這些行按照索引字段進行排序,是以減少了随機IO,排序這才是兩者最大的差別,但是如果被join的表沒用索引呢?那就使用BNLJ了Batched Key Access join
- 什麼是
?Join Buffer
-
-
-
-
會緩存所有參與查詢的列而不是隻有Join的列。Join Buffer
- 可以通過調整
緩存大小join_buffer_size
-
的預設值是256K,join_buffer_size
的最大值在join_buffer_size
版本前是MySQL 5.1.22
,而之後的版本才能在64位作業系統下申請大于4G
的4G
空間。Join Buffer
- 使用
算法需要開啟優化器管理配置的Block Nested-Loop Join
的設定optimizer_switch
為block_nested_loop
,預設為開啟。on
-
-
-
- 在選擇Join算法時,會有優先級,理論上會優先判斷能否使用INLJ、BNLJ:Index Nested-LoopJoin > Block Nested-Loop Join > Simple Nested-Loop Join
- 注:可以使用explain查找驅動表,結果的第一張表即為驅動表,但執行計劃在真正執行時可能發生改變
- on:關聯條件
- where:過濾表中資料的條件
-
- 執行順序:自下而上、從右到左
- 注:對資料庫記錄生效,無法對聚合結果生效,可以過濾掉最大數量記錄的條件必須寫在where子句末尾,不能使用聚合函數(sum、count、max、avg)
- group by:如何将上面過濾出的資料分組
-
- 執行順序:從左往右
- 注:盡量在group by之前使用where過濾,避免之後使用having過濾
- avg:求平均值
- having:對上面已經分組的資料進行過濾的條件
-
- 注:對聚合結果過濾,是以很耗資源,可以使用聚合函數
-
例:篩選統計人口數量大于100W的地區
select region, sum(population), sum(area) from bbc group by region having sum(population)>1000000,不能用where篩選超過100W的地區,因為不存在這樣的一條記錄
- select:檢視結果集中的哪個列或列的計算結果
- distinct:對結果集重複值去重
- order by:按照什麼樣的順序來檢視傳回的資料
-
- 執行順序:從左到右
- 注:很耗資源
- limit:截取出目标頁資料