主頁 > 資料庫 > MySQL查詢優化利刃-EXPLAIN

MySQL查詢優化利刃-EXPLAIN

2020-09-14 08:06:43 資料庫

有一個 ?

遇到這樣一個疑問:當where查詢中In一個索引欄位作為條件,那么在查詢中還會使用到索引嗎?

SELECT * FROM table_name WHERE column_index in (expr)

上面的sql陳述句檢索會使用到索引嗎?帶著這個問題,在網上查找了很多文章,但是有的說 in 會導致放棄索引,全表掃描;有的說Mysql5.5之前的版本不會走,之后的innodb版本會走索引...

越看越迷糊,那答案到底是怎樣的呢?

唯有實踐是檢驗真理的唯一方式!

拿出我們的利刃——EXPLAIN,去剖析 SELECT 陳述句,一探究竟!

EXPLAIN 的用法

在 SELECT 陳述句前加上 EXPLAIN 就可以了 ,例如:

EXPLAIN SELECT * FROM table_name [WHERE Clause]

EXPLAIN 的輸出

EXPLAIN 命令的輸出內容為一個表格形式,表的每一個欄位含義如下:

列名 解釋
id SELECT 查詢的識別符號. 每個 SELECT 都會自動分配一個唯一的識別符號
select_type SELECT 查詢的型別
table 查詢的是哪個表
partitions 匹配的磁區
type join 型別
possible_keys 此次查詢中可能選用的索引
key 此次查詢中確切使用到的索引
ref 哪個欄位或常數與 key 一起被使用;與索引比較的列
rows 顯示此查詢一共掃描了多少行, 這個是一個估計值
filtered 表示此查詢條件所過濾的資料的百分比
extra 額外的資訊
select_type
查詢型別 解釋
SIMPLE 表示此查詢不包含 UNION 查詢或子查詢
PRIMARY 表示此查詢是最外層的查詢
UNION 表示此查詢是 UNION 的第二或隨后的查詢
DEPENDENT UNION UNION 中的第二個或后面的查詢陳述句, 取決于外面的查詢
UNION RESULT UNION 的結果
SUBQUERY 子查詢中的第一個 SELECT
DEPENDENT SUBQUERY 子查詢中的第一個 SELECT,取決于外面的查詢,子查詢依賴于外層查詢的結果
MATERIALIZED Materialized subquery
table

表示查詢涉及的表或衍生表 , 這也可以是以下值之一:

  • <unionM,N>:該行指的是具有和id值的行 的 M并集 N,
  • :該行是指用于與該行的派生表結果id的值 N,派生表可能來自FROM子句中的子查詢 ,
  • :該行是指該行的物化子查詢的結果,其id 值為N,
partitions

查詢將匹配記錄的磁區,該值適用NULL于未磁區的表,

type

聯接型別, 提供了判斷查詢是否高效的重要依據依據,通過 type 欄位,我們判斷此次查詢是全表掃描還是索引掃描等, 從最佳型別到最差型別:

  • system: 該表只有一行(=系統表),這是const聯接型別的特例 ,

  • const: 針對主鍵或唯一索引的等值查詢掃描,最多只回傳一行資料,const 查詢速度非常快,因為它僅僅讀取一次即可 ,

    SELECT * FROM tbl_name WHERE primary_key=1;
    
    SELECT * FROM tbl_name
      WHERE primary_key_part1=1 AND primary_key_part2=2;
    
  • eq_ref: 此型別通常出現在多表的 join 查詢,表示對于前表的每一個結果,都只能匹配到后表的一行結果,并且查詢的比較操作通常是 =,查詢效率較高

    SELECT * FROM ref_table,other_table
      WHERE ref_table.key_column=other_table.column;
    
    SELECT * FROM ref_table,other_table
      WHERE ref_table.key_column_part1=other_table.column
      AND ref_table.key_column_part2=1;
    
  • ref : 此型別通常出現在多表的 join 查詢,針對于非唯一或非主鍵索引,或者是使用了最左前綴規則索引的查詢,ref可以用于使用=或<=> 運算子進行比較的索引列,

    SELECT * FROM ref_table WHERE key_column=expr;
    
    SELECT * FROM ref_table,other_table
      WHERE ref_table.key_column=other_table.column;
    
    SELECT * FROM ref_table,other_table
      WHERE ref_table.key_column_part1=other_table.column
      AND ref_table.key_column_part2=1;
    
  • ref_or_null: 這種連接型別類似于 ref,但是除了MySQL會額外搜索包含NULL值的行,此聯接型別優化最常用于決議子查詢,

    SELECT * FROM ref_table
      WHERE key_column=expr OR key_column IS NULL;
    
  • unique_subquery: 只是一個索引查找函式,它完全替代了子查詢以提高效率,

    value IN (SELECT primary_key FROM single_table WHERE some_expr)
    
  • index_subquery:此連接型別類似于 unique_subquery,它代替IN子查詢,但適用于以下形式的子查詢中的非唯一索引,

  • range: 表示使用索引范圍查詢, 通過索引欄位范圍獲取表中部分資料記錄,這個型別通常出現在 =,<>,>,>=,<,<=,IS NULL,<=>,BETWEEN,IN() 操作中,

    當 type 是 range 時,那么 EXPLAIN 輸出的 ref 欄位為 NULL,并且 key_len 欄位是此次查詢中使用到的索引的最長的那個 ,

    SELECT * FROM tbl_name
      WHERE key_column = 10;
    
    SELECT * FROM tbl_name
      WHERE key_column BETWEEN 10 and 20;
    
    SELECT * FROM tbl_name
      WHERE key_column IN (10,20,30);
    
    SELECT * FROM tbl_name
      WHERE key_part1 = 10 AND key_part2 IN (10,20,30);
    
  • index: 表示全索引掃描(full index scan)和 ALL 型別類似,只不過 ALL 型別是全表掃描,而 index 型別則僅僅掃描所有的索引,而不掃描資料,

    index 型別通常出現在: 所要查詢的資料直接在索引樹中就可以獲取到,而不需要掃描資料,當是這種情況時,Extra 欄位 會顯示 Using index

  • ALL: 表示全表掃描,這個型別的查詢是性能最差的查詢之一,

    我們的查詢不應該出現 ALL 型別的查詢,因為這樣的查詢在資料量大的情況下,對資料庫的性能是巨大的災難,如一個查詢是 ALL 型別查詢,那么一般來說可以對相應的欄位添加索引來避免 ,

possible_keys

表示 MySQL 在查詢時,能夠使用到的索引,

即使有些索引在 possible_keys 中出現,但是并不表示此索引會真正地被 MySQL 使用到,MySQL 在查詢時具體使用了哪些索引,由 key 欄位決定,

key

是 MySQL 在當前查詢時所真正使用到的索引,

key_len

表示查詢優化器使用了索引的位元組數,

這個欄位可以評估組合索引是否完全被使用,或只有最左部分欄位被使用到,key_len 的計算規則如下:

  • 字串
    • char(n): n 位元組長度
    • varchar(n): 如果是 utf8 編碼, 則是 3n + 2位元組; 如果是 utf8mb4 編碼, 則是 4n + 2 位元組
  • 數值型別
  • TINYINT: 1位元組
  • SMALLINT: 2位元組
  • MEDIUMINT: 3位元組
  • INT: 4位元組
  • BIGINT: 8位元組
  • 時間型別
  • DATE: 3位元組
  • TIMESTAMP: 4位元組
  • DATETIME: 8位元組
  • 欄位屬性: NULL 屬性 占用一個位元組,如果一個欄位是 NOT NULL 的, 則沒有此屬性
rows

查詢優化器根據統計資訊,估算 SQL 要查找到結果集需要掃描讀取的資料行數,這個值非常直觀顯示 SQL 的效率好壞,原則上 rows 越少越好,

這個 rows 就是 mysql 認為必須要逐行去檢查和判斷的記錄的條數,舉個例子來說,假如有一個陳述句 select * from t where column_a = 1 and column_b = 2; 全表假設有 100 條記錄,column_a 欄位有索引(非聯合索引),column_b沒有索引,column_a = 1 的記錄有 20 條, column_a = 1 and column_b = 2 的記錄有 5 條,

Extra

EXplain 中的很多額外的資訊會在 Extra 欄位顯示,常見的有以下幾種內容:

  • Using filesort:當 Extra 中有 Using filesort 時,表示 MySQL 需額外的排序操作,不能通過索引順序達到排序效果,一般有 Using filesort,都建議優化去掉,因為這樣的查詢 CPU 資源消耗大,
  • Using index:"覆寫索引掃描",表示查詢在索引樹中就可查找所需資料,不用掃描表資料檔案,往往說明性能不錯
  • Using temporary:查詢有使用臨時表,一般出現于排序,分組和多表 join 的情況,查詢效率不高,建議優化
  • Using where: WHERE子句用于限制哪些行與下一個表匹配或發送給客戶端 ,

得出結論

說到最后,那 WHERE column_index in (expr) 到底走不走索引呢? 答案是不確定的,

走不走索引是由 expr 來決定的,不是一概而論走還是不走,

SELECT * FROM a WHERE id in (1,23,456,7,8)
-- id 是主鍵,查詢是走索引的,type = range,key = PRIMARY
SELECT * FROM a WHERE id in (SELECT b.a_id FROM b WHERE some_expr)
-- id 是主鍵,如果 some_expr 是一個索引查詢,那么 select a 將走索引;
-- some_expr 不是索引查詢,那么 select a 將全表掃描;

上面是兩個通用案例,但到底對不對了,還是自己去實踐最好了,拿起EXPLAIN去剖析吧~

參考文章: https://dev.mysql.com/doc/refman/5.7/en/explain-output.html#explain

轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/32632.html

標籤:MySQL

上一篇:docker下MySQL修改配置

下一篇:MySQL使用order by field()自定義排序

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • GPU虛擬機創建時間深度優化

    **?桔妹導讀:**GPU虛擬機實體創建速度慢是公有云面臨的普遍問題,由于通常情況下創建虛擬機屬于低頻操作而未引起業界的重視,實際生產中還是存在對GPU實體創建時間有苛刻要求的業務場景。本文將介紹滴滴云在解決該問題時的思路、方法、并展示最終的優化成果。 從公有云服務商那里購買過虛擬主機的資深用戶,一 ......

    uj5u.com 2020-09-10 06:09:13 more
  • 可編程網卡芯片在滴滴云網路的應用實踐

    **?桔妹導讀:**隨著云規模不斷擴大以及業務層面對延遲、帶寬的要求越來越高,采用DPDK 加速網路報文處理的方式在橫向縱向擴展都出現了局限性。可編程芯片成為業界熱點。本文主要講述了可編程網卡芯片在滴滴云網路中的應用實踐,遇到的問題、帶來的收益以及開源社區貢獻。 #1. 資料中心面臨的問題 隨著滴滴 ......

    uj5u.com 2020-09-10 06:10:21 more
  • 滴滴資料通道服務演進之路

    **?桔妹導讀:**滴滴資料通道引擎承載著全公司的資料同步,為下游實時和離線場景提供了必不可少的源資料。隨著任務量的不斷增加,資料通道的整體架構也隨之發生改變。本文介紹了滴滴資料通道的發展歷程,遇到的問題以及今后的規劃。 #1. 背景 資料,對于任何一家互聯網公司來說都是非常重要的資產,公司的大資料 ......

    uj5u.com 2020-09-10 06:11:05 more
  • 滴滴AI Labs斬獲國際機器翻譯大賽中譯英方向世界第三

    **桔妹導讀:**深耕人工智能領域,致力于探索AI讓出行更美好的滴滴AI Labs再次斬獲國際大獎,這次獲獎的專案是什么呢?一起來看看詳細報道吧! 近日,由國際計算語言學協會ACL(The Association for Computational Linguistics)舉辦的世界最具影響力的機器 ......

    uj5u.com 2020-09-10 06:11:29 more
  • MPP (Massively Parallel Processing)大規模并行處理

    1、什么是mpp? MPP (Massively Parallel Processing),即大規模并行處理,在資料庫非共享集群中,每個節點都有獨立的磁盤存盤系統和記憶體系統,業務資料根據資料庫模型和應用特點劃分到各個節點上,每臺資料節點通過專用網路或者商業通用網路互相連接,彼此協同計算,作為整體提供 ......

    uj5u.com 2020-09-10 06:11:41 more
  • 滴滴資料倉庫指標體系建設實踐

    **桔妹導讀:**指標體系是什么?如何使用OSM模型和AARRR模型搭建指標體系?如何統一流程、規范化、工具化管理指標體系?本文會對建設的方法論結合滴滴資料指標體系建設實踐進行解答分析。 #1. 什么是指標體系 ##1.1 指標體系定義 指標體系是將零散單點的具有相互聯系的指標,系統化的組織起來,通 ......

    uj5u.com 2020-09-10 06:12:52 more
  • 單表千萬行資料庫 LIKE 搜索優化手記

    我們經常在資料庫中使用 LIKE 運算子來完成對資料的模糊搜索,LIKE 運算子用于在 WHERE 子句中搜索列中的指定模式。 如果需要查找客戶表中所有姓氏是“張”的資料,可以使用下面的 SQL 陳述句: SELECT * FROM Customer WHERE Name LIKE '張%' 如果需要 ......

    uj5u.com 2020-09-10 06:13:25 more
  • 滴滴Ceph分布式存盤系統優化之鎖優化

    **桔妹導讀:**Ceph是國際知名的開源分布式存盤系統,在工業界和學術界都有著重要的影響。Ceph的架構和演算法設計發表在國際系統領域頂級會議OSDI、SOSP、SC等上。Ceph社區得到Red Hat、SUSE、Intel等大公司的大力支持。Ceph是國際云計算領域應用最廣泛的開源分布式存盤系統, ......

    uj5u.com 2020-09-10 06:14:51 more
  • es~通過ElasticsearchTemplate進行聚合~嵌套聚合

    之前寫過《es~通過ElasticsearchTemplate進行聚合操作》的文章,這一次主要寫一個嵌套的聚合,例如先對sex集合,再對desc聚合,最后再對age求和,共三層嵌套。 Aggregations的部分特性類似于SQL語言中的group by,avg,sum等函式,Aggregation ......

    uj5u.com 2020-09-10 06:14:59 more
  • 爬蟲日志監控 -- Elastc Stack(ELK)部署

    傻瓜式部署,只需替換IP與用戶 導讀: 現ELK四大組件分別為:Elasticsearch(核心)、logstash(處理)、filebeat(采集)、kibana(可視化) 下載均在https://www.elastic.co/cn/downloads/下tar包,各組件版本最好一致,配合fdm會 ......

    uj5u.com 2020-09-10 06:15:05 more
最新发布
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:33:24 more
  • MySQL中binlog備份腳本分享

    關于MySQL的二進制日志(binlog),我們都知道二進制日志(binlog)非常重要,尤其當你需要point to point災難恢復的時侯,所以我們要對其進行備份。關于二進制日志(binlog)的備份,可以基于flush logs方式先切換binlog,然后拷貝&壓縮到到遠程服務器或本地服務器 ......

    uj5u.com 2023-04-20 08:28:06 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:27:27 more
  • 快取與資料庫雙寫一致性幾種策略分析

    本文將對幾種快取與資料庫保證資料一致性的使用方式進行分析。為保證高并發性能,以下分析場景不考慮執行的原子性及加鎖等強一致性要求的場景,僅追求最終一致性。 ......

    uj5u.com 2023-04-20 08:26:48 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:26:35 more
  • 云時代,MySQL到ClickHouse資料同步產品對比推薦

    ClickHouse 在執行分析查詢時的速度優勢很好的彌補了MySQL的不足,但是對于很多開發者和DBA來說,如何將MySQL穩定、高效、簡單的同步到 ClickHouse 卻很困難。本文對比了 NineData、MaterializeMySQL(ClickHouse自帶)、Bifrost 三款產品... ......

    uj5u.com 2023-04-20 08:26:29 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:25:13 more
  • Redis 報”OutOfDirectMemoryError“(堆外記憶體溢位)

    Redis 報錯“OutOfDirectMemoryError(堆外記憶體溢位) ”問題如下: 一、報錯資訊: 使用 Redis 的業務介面 ,產生 OutOfDirectMemoryError(堆外記憶體溢位),如圖: 格式化后的報錯資訊: { "timestamp": "2023-04-17 22: ......

    uj5u.com 2023-04-20 08:24:54 more
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:24:03 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:23:11 more