MySQL基礎(九):查詢優化

下面是小凰凰的簡介,看下吧!
💗人生態度:珍惜時間,渴望學習,熱愛音樂,把握命運,享受生活
💗學習技能:網絡 -> 雲計算運維 -> python全棧( 當前正在學習中)
💗您的點贊、收藏、關注是對博主創作的最大鼓勵,在此謝過!
有相關技能問題可以寫在下方評論區,我們一起學習,一起進步。
後期會不斷更新python全棧學習筆記,秉着質量博文爲原則,寫好每一篇博文。

一、單表查詢優化

1、單表查詢的優化點

現在我創建一個單表,我相信理解這些應該不需要看錶了吧,針對問題,優化就完事了!
需求:查詢 category_id 爲1 且 comments 大於 1 的情況下,views 最多的 article_id。
在這裏插入圖片描述很顯然,type 是 ALL,即全表掃描。Extra 裏還出現了 Using filesort(文件內排序)

2、開始優化

# 1.1 新建索引+刪除索引 
# ALTER TABLE `article` ADD INDEX idx_article_ccv ( `category_id` , `comments`, `views` );  alter增加索引,我們採用下面的create方法
create index idx_article_ccv on article(category_id,comments,views); 
 
 
 
# 1.2 第2次EXPLAIN 
EXPLAIN SELECT id,author_id FROM `article` WHERE category_id = 1 AND comments >1 ORDER BY views DESC LIMIT 1; 
  
# 結論: 
# type 變成了 range,這是可以忍受的。但是 extra 裏使用 Using filesort 仍是無法接受的。 
# 但是我們已經建立了索引,爲啥沒用呢? 
# 這是因爲按照 BTree 索引的工作原理, 
# 先排序 category_id, 
# 如果遇到相同的 category_id 則再排序 comments,如果遇到相同的 comments 則再排序 views。 
# 當 comments 字段在聯合索引裏處於中間位置時, 
# 因comments > 1 條件是一個範圍值(所謂 range), 
# MySQL 無法利用索引再對後面的 views 部分進行檢索,即 範圍類型查詢字段後面的索引無效。 
 
 
# 1.3 刪除第一次建立的索引 
DROP INDEX idx_article_ccv ON article; 
 
# 1.4 第2次新建索引 
create index idx_article_cv on article(category_id,views); 
 
# 1.5 第3次EXPLAIN 
EXPLAIN SELECT id,author_id FROM article WHERE category_id = 1 AND comments > 1 ORDER BY views DESC LIMIT 1; 
# 結論:可以看到,type 變爲了 ref,Extra 中的 Using filesort 也消失了,結果非常理想。 

二、雙表查詢優化

1、雙表查詢優化點分析

#  下面開始 explain 分析 
EXPLAIN SELECT * FROM class LEFT JOIN book ON class.card = book.card; 
# 結論: type  有 All ,且雙表都是ALL,接下來我們需要加索引
# 那麼我們到底是選擇給那張表的card字段加索引呢?

在這裏插入圖片描述

2、開始優化

(1)左表建立索引(試優化)
#  添加索引優化 
ALTER TABLE class ADD INDEX X (card); 
 
#  第 2 次 explain 
EXPLAIN SELECT * FROM class LEFT JOIN book ON class.card = book.card; 

在這裏插入圖片描述有一定的優化,type由全表掃描變成了索引樹遍歷!接下來我們看看右表card字段建立索引

(2)右表建立索引(試優化)
#  刪除舊索引  +  新建  +  第 3 次 explain 
DROP INDEX X ON class; 
ALTER TABLE `book` ADD INDEX Y ( `card`);  # 給左連接的右表加索引
EXPLAIN SELECT * FROM class LEFT JOIN book ON class.card = book.card; 

在這裏插入圖片描述
可以看到第二行的 type 變爲了 ref,rows 也由20變成了1,優化比較明顯。
這是由左連接特性決定的。 LEFT JOIN 條件用於確定如何從右表搜索行 , 左邊一定都有 , 所以右邊是我們的關鍵點 , 一定需要建立索引。

3、雙表創建索引建議

  • left join 時,選擇小表作爲驅動表,大表作爲被驅動表。
  • 保證被驅動表的join字段已經被索引
  • inner join 時,mysql 自動選擇小表作爲驅動表。因爲 驅動表無論如何都會被全表掃描。所以掃描次數越少越好
  • 子查詢儘量不要放在被驅動表,有可能使用不到索引。
select a.name ,bc.name from t_emp a left join
         (select b.id , c.name from t_dept b 
         inner join t_emp c on b.ceo = c.id )bc 
         on bc.id = a.deptid.
上段查詢中用到了子查詢,必然 bc 表沒有索引。肯定會進行全表掃描
上段查詢 可以直接使用 兩個 left join 優化
select a.name , c.name from t_emp a
    left outer join t_dept b on a.deptid = b.id
    left outer join t_emp c on b.ceo=c.id
所有條件都可以使用到索引
 
若必須用到子查詢,可將子查詢設置爲驅動表,,因爲驅動表的type 肯定是 all,而子查詢返回的結果表沒有索引,必定也是all

三、三表查詢優化

1、三表查詢優化點

2、開始優化

三表連接查詢,會出現連接緩存!按照兩個表的規律,分別建立兩個索引:
在這裏插入圖片描述效果如下:
在這裏插入圖片描述總結:
後2行的type都是ref且總的rows優化效果很好,效果不錯,因此索引最好設置在需要經常查詢的字段中。
join語句優化:永遠用小的結果集驅動大的結果集,即小表驅動大表

四、子查詢優化

建議先看下:https://blog.csdn.net/weixin_44571270/article/details/107027121
在這裏插入圖片描述上述兩種方法結果一樣,但是一個使用的是in,一個使用的是exists
我們可以說in是子查詢驅動主查詢,即先得出子查詢的結果,再去主查詢拿到id符合條件的記錄!
exists可以說是主查詢驅動子查詢,先是遍歷主查詢得到結果,再拿着主查詢的結果,執行子查詢的where的條件是否成立,成立則返回True,不成立則返回False。因此exists的select語句並沒用,因此你可以隨便填!

因此得出結論:

1. 當子查詢的數據集小於主查詢的數據集,in優於exists
2. 當主查詢的數據集小於子查詢的數據集,exists優於in
爲什麼?'因爲必須符合小表驅動大表的原則!'
3. 至少驅動表的相應索引字段應該建立索引
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章