MySQL特異功能之:Impossible WHERE noticed after reading const tables

用EXPLAIN看MySQL的執行計劃時經常會看到Impossible WHERE noticed after reading const tables這句話,意思是說MySQL通過讀取“const tables”,發現這個查詢是不可能有結果輸出的。比如對下面的表和數據:

  create table t (a int primary key, b int) engine = innodb;

insert into t values(1, 1);
insert into t values(3, 1);

執 行“EXPLAIN select * from t where a = 2”時就會輸出“Impossible WHERE noticed after reading const tables”。

不明白所謂的“const tables”是什麼意思,對MySQL在查詢優化時竟然可以發現一個查詢不可能輸出結果更是感覺不可思議。按數據庫中“傳統”的做法,查詢優化時只會訪 問模式定義和統計信息,而據我所知,數據庫中使用的各種統計信息如EquiDepth、MaxDiff柱狀圖,MCV,屬性的最大值、最小值等都不可能精 確到能夠斷言在上述的表中不存在“a = 2”的記錄。

今天看MySQL Internal手冊時才總算弄明白,原來MySQL並沒有什麼神奇之處,這個Impossible WHERE noticed after reading const tables的結論並不是通過統計信息做出的,而是真的去實際訪問了一遍數據後,發現確實沒有“a = 2”的行才得出的。

當 查詢中對某個表指定了主鍵或非空唯一索引上的等值條件,從而使得最多隻可能產生一條命中結果(只對該表而言)時,MySQL在EXPLAIN之前會優先根 據這一條件查找出對應的記錄,並用記錄的實際值替換查詢中所有用到來自該表的屬性的地方。一個更復雜的例子如下:

  explain select * from t as t1, t as t2 where t1.a = 1 and t2.a = t1.b + 1;


的輸出結果爲(由於排版關係省略了一些輸出內容):
+----+...+-----------------------------------------------------+
| id | ... | Extra |
+----+...+-----------------------------------------------------+
| 1 | ... | Impossible WHERE noticed after reading const tables |
+----+...+-----------------------------------------------------+

MySQL 得出上述查詢不會輸出結果的步驟如下:
1、首先根據t1.a = 1條件找到一條記錄(1,1);
2、將上述記錄中b的值1替換查詢中的 t1.b,即將上述查詢轉化爲等價的“explain select 1, 1,t2.a, t2.b from t as t2 where t2.a = 1 + 1”;
3、優化器計算常量表達式的值,即計算1+1得出結果爲2;
4、優化器根據t2.a = 2條件查找,發現沒有命中記錄;
5、優化器最終打斷出上述查詢不可能輸出結果。


說白了,這個“Impossible WHERE noticed after reading const tables”就不再神祕了。但從這件事,我更加感覺到MySQL是個“怪怪”的數據庫,有很多地方跟慣常的做法不太一樣。很多數據庫會在聯接時將指定了 唯一索引等值條件的表優先執行,作爲查詢執行的第一步,但據我所知只有MySQL將這一步驟提前到查詢優化的第一步來做。這麼做到底在什麼情況下才有好處 好像是個很微妙的問題,對於本文中給出的這兩個例子,在優化時還是執行時做這一步開銷都沒什麼區別。不過這麼做好像沒什麼壞處。

這麼會導 致一個“怪怪”的現象,那就是EXPLAIN有時候也會被阻塞。比如“EXPLAIN select * from t where a = 2 lock in share mode”,同時又有另一個事務插入了一條a = 2的記錄而沒有提交時,EXPLAIN就會在那裏等鎖。

發佈了161 篇原創文章 · 獲贊 14 · 訪問量 68萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章