- 論壇徽章:
- 0
|
用EXPLAIN看MySQL的執(zhí)行計劃時經(jīng)常會看到Impossible WHERE noticed after reading const
tables這句話,意思是說MySQL通過讀取“const tables”,發(fā)現(xiàn)這個查詢是不可能有結(jié)果輸出的。比如對下面的表和數(shù)據(jù): create table t (a int primary key, b int) engine = innodb; insert into t values(1, 1); insert into t values(3, 1); 執(zhí)行“EXPLAIN
select * from t where a = 2”時就會輸出“Impossible WHERE noticed after reading const
tables”。
不明白所謂的“const
tables”是什么意思,對MySQL在查詢優(yōu)化時竟然可以發(fā)現(xiàn)一個查詢不可能輸出結(jié)果更是感覺不可思議。按數(shù)據(jù)庫中“傳統(tǒng)”的做法,查詢優(yōu)化時只會訪問模式定義和統(tǒng)計信息,而據(jù)我所知,數(shù)據(jù)庫中使用的各種統(tǒng)計信息如EquiDepth、MaxDiff柱狀圖,MCV,屬性的最大值、最小值等都不可能精確到能夠斷言在上述的表中不存在“a
= 2”的記錄。
今天看MySQL Internal手冊時才總算弄明白,原來MySQL并沒有什么神奇之處,這個Impossible WHERE
noticed after reading const tables的結(jié)論并不是通過統(tǒng)計信息做出的,而是真的去實際訪問了一遍數(shù)據(jù)后,發(fā)現(xiàn)確實沒有“a =
2”的行才得出的。
當(dāng)查詢中對某個表指定了主鍵或非空唯一索引上的等值條件,從而使得最多只可能產(chǎn)生一條命中結(jié)果(只對該表而言)時,MySQL在EXPLAIN之前會優(yōu)先根據(jù)這一條件查找出對應(yīng)的記錄,并用記錄的實際值替換查詢中所有用到來自該表的屬性的地方。一個更復(fù)雜的例子如下: explain select * from t as t1, t as t2 where t1.a = 1 and t2.a = t1.b + 1;
的輸出結(jié)果為(由于排版關(guān)系省略了一些輸出內(nèi)容): +----+...+-----------------------------------------------------+ | id | ... | Extra | +----+...+-----------------------------------------------------+ | 1 | ... | Impossible WHERE noticed after reading const tables | +----+...+-----------------------------------------------------+
MySQL得出上述查詢不會輸出結(jié)果的步驟如下: 1、首先根據(jù)t1.a = 1條件找到一條記錄(1,1); 2、將上述記錄中b的值1替換查詢中的t1.b,即將上述查詢轉(zhuǎn)化為等價的“explain select 1,
1,t2.a, t2.b from t as t2 where t2.a = 1 +
1”; 3、優(yōu)化器計算常量表達(dá)式的值,即計算1+1得出結(jié)果為2; 4、優(yōu)化器根據(jù)t2.a =
2條件查找,發(fā)現(xiàn)沒有命中記錄; 5、優(yōu)化器最終打斷出上述查詢不可能輸出結(jié)果。
說白了,這個“Impossible WHERE
noticed after reading const
tables”就不再神秘了。但從這件事,我更加感覺到MySQL是個“怪怪”的數(shù)據(jù)庫,有很多地方跟慣常的做法不太一樣。很多數(shù)據(jù)庫會在聯(lián)接時將指定了唯一索引等值條件的表優(yōu)先執(zhí)行,作為查詢執(zhí)行的第一步,但據(jù)我所知只有MySQL將這一步驟提前到查詢優(yōu)化的第一步來做。這么做到底在什么情況下才有好處好像是個很微妙的問題,對于本文中給出的這兩個例子,在優(yōu)化時還是執(zhí)行時做這一步開銷都沒什么區(qū)別。不過這么做好像沒什么壞處。
這么會導(dǎo)致一個“怪怪”的現(xiàn)象,那就是EXPLAIN有時候也會被阻塞。比如“EXPLAIN
select * from t where a = 2 lock in share mode”,同時又有另一個事務(wù)插入了一條a =
2的記錄而沒有提交時,EXPLAIN就會在那里等鎖。
|
|