| SELECT * FROM tbl_name WHERE 0; |
| mysql> EXPLAIN SELECT * FROM tbl_name WHERE 0G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: NULL type: NULL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: NULL Extra: Impossible WHERE |
| SELECT col3 FROM mytable WHERE col1 = ’some value’ AND col2 = ’some other value’; |
| WHERE mycol < 4 / 2 WHERE mycol * 2 < 4 |
| SELECT * FROM mytbl WHERE YEAR(date_col) < 1990; |
| WHERE date_col < ’1990-01-01’ |
| WHERE TO_DAYS(date_col) - TO_DAYS(CURDATE()) < cutoff WHERE TO_DAYS(date_col) < cutoff + TO_DAYS(CURDATE()) WHERE date_col < DATE_ADD(CURDATE(), INTERVAL cutoff DAY) |
| WHERE col_name LIKE ’%string%’ |
| WHERE last_name LIKE ’Mac%’ |
| WHERE last_name >= ’Mac’ AND last_name < ’Mad’ |
這種優(yōu)化不能應(yīng)用于使用了REGEXP操作符的模式匹配。REGEXP表達(dá)式永遠(yuǎn)不會(huì)被優(yōu)化。
幫助優(yōu)化器更好的判斷索引的效率。在默認(rèn)情況下,當(dāng)你把索引列的值與常量進(jìn)行比較的時(shí)候,優(yōu)化器會(huì)假設(shè)鍵值在索引內(nèi)部是均勻分布的。在決定進(jìn)行常量比較是否使用索引的時(shí)候,優(yōu)化器會(huì)快速地檢查索引,估計(jì)出會(huì)用到多少個(gè)實(shí)體(entry)。對(duì)應(yīng)MyISAM、InnoDB和BDB數(shù)據(jù)表來說,你可以使用ANALYZE TABLE讓服務(wù)器執(zhí)行對(duì)鍵值的分析。它會(huì)為優(yōu)化器提供更好的信息。
使用EXPLAIN驗(yàn)證優(yōu)化器的操作。EXPLAIN語句可以告訴你是否使用了索引。當(dāng)你試圖用另外的方式編寫語句或檢查添加索引是否會(huì)提高查詢執(zhí)行效率的時(shí)候,這些信息對(duì)你是有幫助的。
在必要的時(shí)候給優(yōu)化器一些提示。正常情況下,MySQL優(yōu)化器自由地決定掃描數(shù)據(jù)表的次序來最快地檢索數(shù)據(jù)行。在有些場(chǎng)合中優(yōu)化器沒有作出最佳選擇。如果你察覺這種現(xiàn)象發(fā)生了,就可以使用STRAIGHT_JOIN關(guān)鍵字來重載優(yōu)化器的選擇。帶有STRAIGHT_JOIN的聯(lián)結(jié)類似于交叉聯(lián)結(jié),但是強(qiáng)迫數(shù)據(jù)表按照FROM子句中指定的次序來聯(lián)結(jié)。
在SELECT語句中有兩個(gè)地方可以指定STRAIGHT_JOIN。你可以在SELECT關(guān)鍵字和選擇列表之間的位置指定,這樣會(huì)對(duì)語句中所有的交叉聯(lián)結(jié)產(chǎn)生影響;你也可以在FROM子句中指定。下面的兩個(gè)語句功能相同:
| SELECT STRAIGHT_JOIN ... FROM t1, t2, t3 ... ; SELECT ... FROM t1 STRAIGHT_JOIN t2 STRAIGHT_JOIN t3 ... ; |
| SELECT * FROM mytbl WHERE num_col = 4; SELECT * FROM mytbl WHERE num_col = ’4’; |
| SELECT * FROM mytbl WHERE str_col = 4; |
使用EXPLAIN來檢查優(yōu)化器的操作
EXPLAIN對(duì)于了解優(yōu)化器生成的、用于處理語句的執(zhí)行計(jì)劃的內(nèi)部信息是很有幫助的。在這一部分中,我們將解釋EXPLAIN的兩種用途:
? 查看采用不同的方式編寫的查詢是否影響了索引的使用。
? 查看向數(shù)據(jù)表添加索引對(duì)優(yōu)化器生成高效率執(zhí)行計(jì)劃的能力的影響。
這一部分只討論與示例相關(guān)的EXPLAIN輸入字段。
前面,在"優(yōu)化器是如何工作的"部分中我們得出的觀點(diǎn)是,你編寫表達(dá)式的方式將決定優(yōu)化器是否能使用可用的索引。特別是上面的討論使用了下面三個(gè)邏輯相等的WHERE子句的例子,只有第三個(gè)允許使用索引:
| WHERE TO_DAYS(date_col) - TO_DAYS(CURDATE()) < cutoff WHERE TO_DAYS(date_col) < cutoff + TO_DAYS(CURDATE()) WHERE date_col < DATE_ADD(CURDATE(), INTERVAL cutoff DAY) |
| mysql> ALTER TABLE member ADD INDEX (expiration); |
| mysql> EXPLAIN SELECT * FROM MEMBER -> WHERE TO_DAYS(expiration) - TO_DAYS(CURDATE()) < 30G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: MEMBER type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 102 Extra: Using where mysql> EXPLAIN SELECT * FROM MEMBER -> WHERE TO_DAYS(expiration) < 30 + TO_DAYS(CURDATE())G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: MEMBER type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 102 Extra: Using where mysql> EXPLAIN SELECT * FROM MEMBER -> WHERE expiration < DATE_ADD(CURDATE(), INTERVAL 30 DAY)G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: MEMBER type: range possible_keys: expiration key: expiration key_len: 4 ref: NULL rows: 6 Extra: Using where |
| mysql> SELECT t1.i1, t2.i2 FROM t1, t2 WHERE t1.i1 = t2.i2; +------+------+ | i1 | i2 | +------+------+ | 1 | 1 | | 2 | 2 | | 3 | 3 | | 4 | 4 | | 5 | 5 | ... |
| mysql> EXPLAIN SELECT t1.i1, t2.i2 FROM t1, t2 WHERE t1.i1 = t2.i2G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: t1 type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 1000 Extra: *************************** 2. row *************************** id: 1 select_type: SIMPLE table: t2 type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 1000 Extra: Using where |
為了使這個(gè)查詢的效率更高,給其中一個(gè)聯(lián)結(jié)列添加索引并重新執(zhí)行EXPLAIN語句:
| mysql> ALTER TABLE t2 ADD INDEX (i2); mysql> EXPLAIN SELECT t1.i1, t2.i2 FROM t1, t2 WHERE t1.i1 = t2.i2G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: t1 type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 1000 Extra: *************************** 2. row *************************** id: 1 select_type: SIMPLE table: t2 type: ref possible_keys: i2 key: i2 key_len: 5 ref: sampdb.t1.i1 rows: 10 Extra: Using where; Using index |
| mysql> ALTER TABLE t1 ADD INDEX (i1); mysql> EXPLAIN SELECT t1.i1, t2.i2 FROM t1, t2 WHERE t1.i1 = t2.i2G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: t1 type: index possible_keys: i1 key: i1 key_len: 5 ref: NULL rows: 1000 Extra: Using index *************************** 2. row *************************** id: 1 select_type: SIMPLE table: t2 type: ref possible_keys: i2 key: i2 key_len: 5 ref: sampdb.t1.i1 rows: 10 Extra: Using where; Using index |
| mysql> ANALYZE TABLE t1, t2; mysql> EXPLAIN SELECT t1.i1, t2.i2 FROM t1, t2 WHERE t1.i1 = t2.i2G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: t1 type: index possible_keys: i1 key: i1 key_len: 5 ref: NULL rows: 1000 Extra: Using index *************************** 2. row *************************** id: 1 select_type: SIMPLE table: t2 type: ref possible_keys: i2 key: i2 key_len: 5 ref: sampdb.t1.i1 rows: 1 Extra: Using where; Using index |
重載優(yōu)化過程
這個(gè)過程聽起來多余,但是有時(shí)候你還是希望去掉某些MySQL優(yōu)化行為的:
重載優(yōu)化器的表聯(lián)結(jié)次序。使用STRAIGHT_JOIN強(qiáng)迫優(yōu)化器按照特定的次序使用數(shù)據(jù)表。在這樣操作的時(shí)候,你必須對(duì)數(shù)據(jù)表進(jìn)行排序,這樣才能保證第一張表是被選擇的行數(shù)最少的表。如果你不能確定被選擇行數(shù)最少的是哪一張表,那么就把行數(shù)最多的放到第一的位置。換句話說,試著對(duì)表進(jìn)行排序,使最有約束力的選擇出現(xiàn)在最前面。你對(duì)可能的備選數(shù)據(jù)行縮小地越早,執(zhí)行查詢的性能就越好。請(qǐng)確保在帶有STRAIGHT_JOIN和不帶STRAIGHT_JOIN的時(shí)候分別執(zhí)行該查詢。有時(shí)候由于某些原因的存在,優(yōu)化器沒有按照你認(rèn)定的方式聯(lián)結(jié)數(shù)據(jù)表,STRAIGHT_JOIN也可能沒有實(shí)際的幫助作用。
另一個(gè)可能性是在聯(lián)結(jié)的數(shù)據(jù)表列表中的某個(gè)表的后面使用FORCE INDEX、USE INDEX和IGNORE INDEX調(diào)節(jié)符來告訴MySQL如何使用索引。這在優(yōu)化器沒有做出正確選擇的時(shí)候是有用處的。
以最小的代價(jià)清空一張表。當(dāng)需要完全地清空一張MyISAM數(shù)據(jù)表的時(shí)候,最快的方法是刪除它并利用它的.frm文件中存儲(chǔ)的腳本來重新建立它。使用TRUNCATE TABLE語句實(shí)現(xiàn):
| TRUNCATE TABLE tbl_name; |
| DELETE FROM tbl_name; |
| DELETE FROM tbl_name WHERE 1; |
新聞熱點(diǎn)
疑難解答
圖片精選