1. 程式人生 > >MySQL執行計劃顯示與執行過程不符合一例

MySQL執行計劃顯示與執行過程不符合一例

一 建表和現象的過程如下

CREATE TABLE t1 (id1 INT, a1 INT, b1 INT, PRIMARY KEY(id1));
CREATE TABLE t3 (id3 INT UNIQUE, a3 INT, b3 INT);

INSERT INTO t1 VALUES (1, 1, NULL);
INSERT INTO t3 VALUES (1, 1, NULL);

mysql> select * from (select * from t1 where id1 =(select id3 from t3 where id3=1)) t;
+-----+------+------+
| id1 | a1 | b1 |
+-----+------+------+
| 1 | 1 | NULL |
+-----+------+------+
1 row in set (0.01 sec)

mysql> explain extended select * from (select * from t1 where id1=(select id3 from t3 where id3=1)) t;
+----+-------------+------------+--------+---------------+---------+---------+-------+------+----------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+--------+---------------+---------+---------+-------+------+----------+-------------+
| 1 | PRIMARY | <derived2> | system | NULL | NULL | NULL | NULL | 1 | 100.00 | NULL |
| 2 | DERIVED | t1 | const | PRIMARY | PRIMARY | 4 | const | 1 | 100.00 | NULL |
| 3 | SUBQUERY | t3 | const | id3 | id3 | 5 | const | 1 | 100.00 | Using index |
+----+-------------+------------+--------+---------------+---------+---------+-------+------+----------+-------------+
3 rows in set, 1 warning (0.00 sec)

mysql> show warnings;
+-------+------+-----------------------------------------------------------------------+
| Level | Code | Message |
+-------+------+-----------------------------------------------------------------------+
| Note | 1003 | /* select#1 */ select '1' AS `id1`,'1' AS `a1`,NULL AS `b1` from dual |
+-------+------+-----------------------------------------------------------------------+
1 row in set (0.00 sec)

二 分析:
首先, 察看執行計劃:
1 id值為1的select_type值為PRIMARY, 這是一個'<derived2>'表,表示子查詢出現在FROM子句中,且本行的內容是一個類似“殼”一樣的並無多大實質意義的‘虛表’,'<derived2>'中的數字2來自於下一行id為2的結果。而別名為t的子查詢,確實出現在最外層的FROM中。
2 id值為2的select_type值為DERIVED,表示這是一個被驅動的表(被驅動的FROM子句中的子查詢).
3 id值為3的select_type值為SUBQUERY,表示巢狀中的第二個在t3表上的子查詢,沒有被優化為其他型別(優化可如子查詢被消除後轉為內連線)。

其次,察看警告資訊:
1 FROM子句後的表變為了‘dual’這一虛表,t1和t2全部消失。為什麼?
2 MySQL在優化的過程中,利用等式的性質,推知了:
  2.1 id1=id3=1
  2.2 查詢語句從邏輯推理上,就可以變形為:select * from t1 where id1=1
      此時,子查詢其實被消除了,但是執行計劃中沒有體現之一點,這是執行計劃錯誤之處。
  2.3 進一步,t1表上id1列是主鍵,所以根據索引,可以查知*對應的目標列的值:這樣,邏輯推理上,就可以變形為:
      select '1' AS `id1`,'1' AS `a1`,NULL AS `b1` from t1 where id1=1
  2.4 因為目標列的值已經能夠在優化的過程中得知,所以FROM子句中的表,可被標識為“常量表”。
3 於是,在顯示查詢執行計劃的後期(explain命令後期),程式碼中有個判斷:如果表全部是常量表且已經是“被優化了的(optimized_away)”則把FROM子句中的表物件,用“dual”替換。這就是警告中為什麼會出現“from dual”的原因。

再次,執行計劃和警告資訊顯示存在不一致,那麼,MySQL在執行的時候,是按照誰來執行呢?
這點可以通過跟蹤程式碼進行分析。
執行過程如下:
1 優化階段:即生成執行計劃階段

  MySQL在優化階段的過程,就如執行計劃顯示的結果一樣,對各個子句進行著執行計劃顯示的過程,先是因為FROM子句中的子查詢執行id為1的過程,然後是對被驅動的id為2的優化,在沒有結束id為2的優化的過程中,發現id為2的子句是子查詢,就巢狀呼叫去優化子查詢,於是引發了等式化簡等過程。
  在運用各種技術做各種化簡的過程中,一些值或結果已經得知,順帶即完成了一些求解的工作。
  這也說明一個問題:有的朋友問id間的序號表明了一個什麼樣的執行次序?因為巢狀的關係,首先啟動的是id值小的,在id值為小的執行過程中,接著又啟動了id值為大的查詢子句,所以,最先執行完畢的,是id值大者;最先執行的,是id值小者。
2 執行階段:
  已經知道是一個常量求解,且結果在優化過程中得知,直接輸出。
  這也解釋了警告資訊中得到的是“from dual”,與執行過程的含義,相符。即:執行階段,查詢計劃表明的過程已經結束了。

三 補充說明

mysql>  explain extended select * from (select * from t1 where id1 in (select id3 from t3 where id3=5)) t;
    -> ;
+----+-------------+------------+--------+---------------+---------+---------+-------+------+----------+-------------+
| id | select_type | table      | type   | possible_keys | key     | key_len | ref   | rows | filtered | Extra       |
+----+-------------+------------+--------+---------------+---------+---------+-------+------+----------+-------------+
|  1 | PRIMARY     | <derived2> | system | NULL          | NULL    | NULL    | NULL  |    1 |   100.00 | NULL        |
|  2 | DERIVED     | t1         | const  | PRIMARY       | PRIMARY | 4       | const |    1 |   100.00 | NULL        |
|  2 | DERIVED     | t3         | const  | id3           | id3     | 5       | const |    1 |   100.00 | Using index |
+----+-------------+------------+--------+---------------+---------+---------+-------+------+----------+-------------+
3 rows in set, 1 warning (49.53 sec)

mysql> show warnings;
+-------+------+-----------------------------------------------------------------------+
| Level | Code | Message                                                               |
+-------+------+-----------------------------------------------------------------------+
| Note  | 1003 | /* select#1 */ select '5' AS `id1`,'5' AS `a1`,NULL AS `b1` from dual |
+-------+------+-----------------------------------------------------------------------+
1 row in set (0.00 sec)

"標題三"中和"標題一"中的SQL差別在於巢狀的子查詢的形式是等號還是IN。

而IN的形式,被MySQL識別優化了標識子查詢未“DERIVED ”了,這是MySQL從形式上目前只支援IN形式的子查詢優化的優化,對於等號這樣的形式,不支援。但是,從等式性質上,最終對"標題一"中的SQL進行了優化。

相關推薦

MySQL執行計劃顯示執行過程不符合一

一 建表和現象的過程如下 CREATE TABLE t1 (id1 INT, a1 INT, b1 INT, PRIMARY KEY(id1));CREATE TABLE t3 (id3 INT UNIQUE, a3 INT, b3 INT); INSERT INTO t1 VALUES (1, 1, NU

MySQL執行計劃理解實踐

SQL執行過程和優化器 首先看一下MySQL中,一條sql的執行過程,這裡主要是引用了《高效能MySQL》中的內容: 1、客戶端傳送一條查詢給伺服器 2、伺服器先檢查查詢快取,如果命中快取則立刻返回儲存在快取中的結果,否則進入下一階段。 3、伺服器端

loadrunner學習筆記-場景計劃方式執行模式

手工場景-計劃方式scenario :多個指令碼之間按照設定的場景計劃來統一執行。group : 多個指令碼之間按照獨立設定模式跑,各個指令碼可以單獨設定虛擬使用者,執行時間等手工執行場景-執行模式real - world schedule (實際計劃)可以通過add  ac

mysql 的 job建立執行

1.建立job 每天的凌晨0點10分執行指定的procedure pro_test:CREATE EVENT `event_test` ON SCHEDULE EVERY 1 DAY STARTS '2013-10-15 00:10:00'       ON COMPLET

String,StringBufferStringBuilder的區別|執行緒安全執行緒不安全

轉載自https://www.cnblogs.com/xingzc/p/6277581.html侵權刪 String 字串常量 StringBuffer 字串變數(執行緒安全) StringBuilder 字串變數(非執行緒安全)  簡要的說, String 型別和 StringBuf

學習筆記-多執行緒程式設計執行緒同步

    執行緒基礎  程序與執行緒 我們執行一個exe,就是一個程序例項,系統中有很多個程序。每一個程序都有自己的記憶體地址空間,每個程序相當於一個獨立的邊界,有自己的獨佔的資源,程序之間不能共享程式碼和資料空間。 每一個程序有一個或多個執行緒,程

執行緒第三課——多執行緒初探執行緒的生命週期

  這節課我們來進入多執行緒,來初步感受下多執行緒,並瞭解下執行緒的宣告週期   Demo 01: public static void main(String[] args) {     //直接點,懶得想新的執行緒名了 &nb

Java多執行緒核心技術(六)執行緒組執行緒異常

本文應注重掌握如下知識點: 執行緒組的使用 如何切換執行緒狀態 SimpleDataFormat 類與多執行緒的解決辦法 如何處理執行緒的異常 1.執行緒的狀態 執行緒物件在不同執行時期有不同的狀態,狀態資訊就處於State列舉類中,如圖所示: 執行緒狀態 初始(NEW):新建立了一個執行緒物件,但還

Dubbo學習筆記8:Dubbo的執行緒模型執行緒池策略

Dubbo預設的底層網路通訊使用的是Netty,服務提供方NettyServer使用兩級執行緒池,其中 EventLoopGroup(boss) 主要用來接受客戶端的連結請求,並把接受的請求分發給 EventLoopGroup(worker) 來處理,boss和worker執

001.多執行緒-程序執行緒的區別

什麼是程序?顧名思義,就是進行中的程式,也就是執行中的程式。我們開啟電腦的工作管理員可以看到: 此時,執行中的360瀏覽器,Google瀏覽器等都是獨立的一個程序,他們擁有相應的系統資源,比如:CPU

Java——設定執行緒等待執行緒喚醒

//執行緒間的通訊:執行緒的任務不同,但是執行緒操作的資料相同 /* wait(),notify(),notifyAll()必須用在同步中,因為同步中才有鎖 指明讓持有哪個鎖的執行緒去等待或被喚醒 */ //還是上次的例子,實現存一個輸出一個,而不是輸出一大堆

寫一下單模式,考慮執行緒安全執行緒不安全的情況

凡是提到設計模式,面試官很喜歡問最簡單的單例模式。 方法一 單例模式最簡單的寫法如下 public class SingletonPatternA { private static SingletonPatternA instance =

執行緒池執行緒佇列分析-優

·  執行緒池是物件池的一個有用的例子,它能夠節省在建立它們時候的資源開銷。並且執行緒池對系統中的執行緒數量也起到了很好的限制作用。 ·  執行緒池中的執行緒數量必須仔細的設定,否則冒然增加執行緒數量只會帶來效能的下降。 ·  在定製ThreadPoolExecutor時,

執行緒ID執行緒ID

[1]NPTL標準     1.目前的執行緒實現是 Native POSIX Thread Library,簡稱NPTL 。     2.執行緒又被稱為輕量級程序。     3.每一個使用者態的執行緒,在核心之

Java--辨別執行緒安全執行緒不安全

在學習Java的時候經常會發現有很多名稱相似的類,比如HashMap和Hashtable,StringBuffer和StringBuilder等等,他們的名稱相似,功能也有相似的地方,所以初學者在學習之中往往會很疑惑,他們都有哪些不同呢?而在深入研究這個問題的時

TigerGraph開源十大圖資料庫演算法庫 ——基於GSQL的圖靈完備的演算法,執行演算法查詢執行GSQL查詢動作一致

日前,全球速度最快的企業級圖分析平臺TigerGraph宣佈,正式開源 TigerGraph GSQL 圖資料庫演算法庫,釋出三大類共十大核心演算法。 通過開放這些演算法庫,將為使用者提供圖分析的演算法模板和示範,讓使用者以更加簡單易用的方式支援更廣泛場景的業務分析。 目前,使用者可以從gi

程式設計思想之多執行多程序(2)——執行緒優先順序執行緒安全

《程式設計思想之多執行緒與多程序(1)——以作業系統的角度述說執行緒與程序》一文詳細講述了執行緒、程序的關係及在作業系統中的表現,這是多執行緒學習必須瞭解的基礎。本文將接著講一下執行緒優先順序和執行緒安全。 執行緒優先順序 現在主流作業系統(

作業系統核心原理-4.執行緒原理(上):執行緒基礎執行緒同步

  我們都知道,程序是運轉中的程式,是為了在CPU上實現多道程式設計而發明的一個概念。但是程序在一個時間只能幹一件事情,如果想要同時幹兩件或者多件事情,例如同時看兩場電影,我們自然會想到傳說中的分身術,就像孫悟空那樣可以變出多個真身。雖然我們在現實中無法分身,但程序卻可以辦到,辦法就是執行緒。執行緒就是我們為

Java 多執行緒(七)——執行緒組執行緒池

1 執行緒組 1.1 概述 Java中使用ThreadGroup來表示執行緒組,它可以對一批執行緒進行分類管理。對執行緒組的控管理,即同時控制執行緒組裡面的這一批執行緒。 使用者建立的所有執行緒都屬於指定執行緒組,如果沒有顯示指定屬於哪個執行緒組,那麼

執行緒安全執行緒同步

執行緒同步 同步就是協同步調,按預定的先後次序進行執行。如:你說完,我再說。 “同”字從字面上容易理解為一起動作,其實不是,“同”字應是指協同、協助、互相配合。 如程序、執行緒同步,可理解為程序或執行緒A和B一塊配合,A執行到一定程度時要依靠B的某個結果,於是停下來,示意B執行;B依言執行,再將結