24. #### [](https://github.com/KeKe-Li/data-structures-questions/blob/master/src/chapter05/golang.01.md#explain%E5%91%BD%E4%BB%A4%E6%9C%89%E4%BB%80%E4%B9%88%E7%94%A8)Explain命令有什么用
在開發的過程中,我們有時會用慢查詢去記錄一些執行時間比較久的Sql語句,找出這些Sql語句并不意味著完事了,這個時候我們就需要用到explain這個命令來查看一個這些Sql語句的執行計劃,查看該Sql語句有沒有使用上了索引,有沒有做全表掃描,這些都可以通過explain命令來查看。 所以我們深入了解Mysql的基于開銷的優化器,還可以獲得很多可能被優化器考慮到的訪問策略的細節,以及當運行SQL語句時哪種策略預計會被優化器采用。
~~~shell
> explain select * from server;
+----+-------------+---------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+------+---------------+------+---------+------+------+-------+
| 1 | SIMPLE | server | ALL | NULL | NULL | NULL | NULL | 1 | NULL |
+----+-------------+---------+------+---------------+------+---------+------+------+-------+
1 row in set (0.03 sec)
~~~
expain出來的信息有10列,分別是`id、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra`.
~~~gfm
id: select選擇標識符.
select_type: 表示查詢的類型.
table: 輸出結果集的表.
partitions: 匹配的分區.
type: 表示表的連接類型.
possible_keys: 表示查詢時,可能使用的索引.
key: 表示實際使用的索引.
key_len: 索引字段的長度.
ref: 列與索引的比較.
rows: 掃描出的行數(估算的行數).
filtered: 按表條件過濾的行百分比.
Extra: 執行情況的描述和說明.
~~~
* id
id是Sql執行的順序的標識,Sql從大到小的執行:
1. id相同時,執行順序由上至下.
2. 如果是子查詢,id的序號會遞增,id值越大優先級越高,越先被執行.
3. id如果相同,可以認為是一組,從上往下順序執行;在所有組中,id值越大,優先級越高,越先執行.
* select\_type 查詢的類型
示查詢中每個select子句的類型:
1. SIMPLE(簡單SELECT,不使用UNION或子查詢等)
2. PRIMARY(查詢中若包含任何復雜的子部分,最外層的select被標記為PRIMARY)
3. UNION(UNION中的第二個或后面的SELECT語句)
4. DEPENDENT UNION(UNION中的第二個或后面的SELECT語句,取決于外面的查詢)
5. UNION RESULT(UNION的結果)
6. SUBQUERY(子查詢中的第一個SELECT)
7. DEPENDENT SUBQUERY(子查詢中的第一個SELECT,取決于外面的查詢)
8. DERIVED(派生表的SELECT, FROM子句的子查詢)
9. UNCACHEABLE SUBQUERY(一個子查詢的結果不能被緩存,必須重新評估外鏈接的第一行)
* table
table顯示這一行的數據是關于哪張表的,有時不是真實的表名字,看到的是derivedx.
~~~shell
> explain select * from (select * from ( select * from t1 where id=2602) a) b;
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
| 1 | PRIMARY | <derived2> | system | NULL | NULL | NULL | NULL | 1 | |
| 2 | DERIVED | <derived3> | system | NULL | NULL | NULL | NULL | 1 | |
| 3 | DERIVED | t1 | const | PRIMARY,idx_t1_id | PRIMARY | 4 | | 1 | |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
~~~
* type 表的連接類型
type表示Mysql在表中找到所需行的方式,又稱“訪問類型”。
常用的類型有: ALL, index, range, ref, eq\_ref, const, system, NULL(從左到右,性能從差到好).
1. ALL:Full Table Scan, Mysql將遍歷全表以找到匹配的行.
2. index: Full Index Scan,index與ALL區別為index類型只遍歷索引樹.
3. range:只檢索給定范圍的行,使用一個索引來選擇行.
4. ref: 表示上述表的連接匹配條件,即哪些列或常量被用于查找索引列上的值.
5. eq\_ref: 類似ref,區別就在使用的索引是唯一索引,對于每個索引鍵值,表中只有一條記錄匹配,簡單來說,就是多表連接中使用primary key或者 unique key作為關聯條件.
6. const、system: 當Mysql對查詢某部分進行優化,并轉換為一個常量時,使用這些類型訪問。如將主鍵置于where列表中,Mysql就能將該查詢轉換為一個常量,system是const類型的特例,當查詢的表只有一行的情況下,使用system.
7. NULL: Mysql在優化過程中分解語句,執行時甚至不用訪問表或索引,例如從一個索引列里選取最小值可以通過單獨索引查找完成。
* possible\_keys
possible\_keys指出Mysql能使用哪個索引在表中找到記錄,查詢涉及到的字段上若存在索引,則該索引將被列出,但不一定被查詢使用.
該列完全獨立于`EXPLAIN`輸出所示的表的次序。這意味著在`possible_keys`中的某些鍵實際上不能按生成的表次序使用。 如果該列是NULL,則沒有相關的索引。在這種情況下,可以通過檢查WHERE子句看是否它引用某些列或適合索引的列來提高你的查詢性能。如果是這樣,創造一個適當的索引并且再次用EXPLAIN檢查查詢.
* Key
key列顯示MySql實際決定使用的鍵(索引).
如果沒有選擇索引,鍵是NULL。要想強制Mysql使用或忽視`possible_keys`列中的索引,在查詢中使用`FORCE INDEX、USE INDEX`或者`IGNORE INDEX`。
* key\_len
key\_len表示索引中使用的字節數,可通過該列計算查詢中使用的索引的長度(key\_len顯示的值為索引字段的最大可能長度,并非實際使用長度,即key\_len是根據表定義計算而得,不是通過表內檢索出的)不損失精確性的情況下,長度越短越好 .
* ref
ref表示上述表的連接匹配條件,即哪些列或常量被用于查找索引列上的值.
* rows
rows表示Mysql根據表統計信息及索引選用情況,估算的找到所需的記錄所需要讀取的行數.
* Extra執行情況的描述和說明
該列包含Mysql解決查詢的詳細信息,有以下幾種情況:
1. Using where:列數據是從僅僅使用了索引中的信息而沒有讀取實際的行動的表返回的,這發生在對表的全部的請求列都是同一個索引的部分的時候,表示mysql服務器將在存儲引擎檢索行后再進行過濾.
2. Using temporary:表示Mysql需要使用臨時表來存儲結果集,常見于排序和分組查詢.
3. Using filesort:Mysql中無法利用索引完成的排序操作稱為“文件排序”
4. Using join buffer:改值強調了在獲取連接條件時沒有使用索引,并且需要連接緩沖區來存儲中間結果。如果出現了這個值,那應該注意,根據查詢的具體情況可能需要添加索引來改進能。
5. Impossible where:這個值強調了where語句會導致沒有符合條件的行。
6. Select tables optimized away:這個值意味著僅通過使用索引,優化器可能僅從聚合函數結果中返回一行.
- Golang基礎
- Go中new與make的區別
- Golang中除了加Mutex鎖以外還有哪些方式安全讀寫共享變量
- 無緩沖Chan的發送和接收是否同步
- Golang并發機制以及它所使用的CSP并發模型.
- Golang中常用的并發模型
- Go中對nil的Slice和空Slice的處理是一致的嗎
- 協程和線程和進程的區別
- Golang的內存模型中為什么小對象多了會造成GC壓力
- Go中數據競爭問題怎么解決
- 什么是channel,為什么它可以做到線程安全
- Golang垃圾回收算法
- GC的觸發條件
- Go的GPM如何調度
- 并發編程概念是什么
- Go語言的棧空間管理是怎么樣的
- Goroutine和Channel的作用分別是什么
- 怎么查看Goroutine的數量
- Go中的鎖有哪些
- 怎么限制Goroutine的數量
- Channel是同步的還是異步的
- Goroutine和線程的區別
- Go的Struct能不能比較
- Go的defer原理是什么
- Go的select可以用于什么
- Context包的用途是什么
- Go主協程如何等其余協程完再操作
- Go的Slice如何擴容
- Go中的map如何實現順序讀取
- Go中CAS是怎么回事
- Go中的逃逸分析是什么
- Go值接收者和指針接收者的區別
- Go的對象在內存中是怎樣分配的
- 棧的內存是怎么分配的
- 堆內存管理怎么分配的
- 在Go函數中為什么會發生內存泄露
- G0的作用
- Go中的鎖如何實現
- Go中的channel的實現
- 棧的內存是怎么分配的2
- 堆內存管理怎么分配的2
- Go中的map的實現
- Go中的http包的實現原理
- Goroutine發生了泄漏如何檢測
- Go函數返回局部變量的指針是否安全
- Go中兩個Nil可能不相等嗎
- Goroutine和KernelThread之間是什么關系
- 為何GPM調度要有P
- 如何在goroutine執行一半就退出協程
- Mysql基礎
- Mysql索引用的是什么算法
- Mysql事務的基本要素
- Mysql的存儲引擎
- Mysql事務隔離級別
- Mysql高可用方案有哪些
- Mysql中utf8和utf8mb4區別
- Mysql中樂觀鎖和悲觀鎖區別
- Mysql索引主要是哪些
- Mysql聯合索引最左匹配原則
- 聚簇索引和非聚簇索引區別
- 如何查詢一個字段是否命中了索引
- Mysql中查詢數據什么情況下不會命中索引
- Mysql中的MVCC是什么
- Mvcc和Redolog和Undolog以及Binlog有什么不同
- Mysql讀寫分離以及主從同步
- InnoDB的關鍵特性
- Mysql如何保證一致性和持久性
- 為什么選擇B+樹作為索引結構
- InnoDB的行鎖模式
- 哈希(hash)比樹(tree)更快,索引結構為什么要設計成樹型
- 為什么索引的key長度不能太長
- Mysql的數據如何恢復到任意時間點
- Mysql為什么加了索引可以加快查詢
- Explain命令有什么用
- Redis基礎
- Redis的數據結構及使用場景
- Redis持久化的幾種方式
- Redis的LRU具體實現
- 單線程的Redis為什么快
- Redis的數據過期策略
- 如何解決Redis緩存雪崩問題
- 如何解決Redis緩存穿透問題
- Redis并發競爭key如何解決
- Redis的主從模式和哨兵模式和集群模式區別
- Redis有序集合zset底層怎么實現的
- 跳表的查詢過程是怎么樣的,查詢和插入的時間復雜度
- 網絡協議基礎
- TCP和UDP有什么區別
- TCP中三次握手和四次揮手
- TCP的LISTEN狀態是什么
- 常見的HTTP狀態碼有哪些
- 301和302有什么區別
- 504和500有什么區別
- HTTPS和HTTP有什么區別
- Quic有什么優點相比Http2
- Grpc的優缺點
- Get和Post區別
- Unicode和ASCII以及Utf8的區別
- Cookie與Session異同
- Client如何實現長連接
- Http1和Http2和Grpc之間的區別是什么
- Tcp中的拆包和粘包是怎么回事
- TFO的原理是什么
- TIME_WAIT的作用
- 網絡的性能指標有哪些