一、 MySQL建表,字段需設(shè)置為非空,需設(shè)置字段默認(rèn)值。
二、 MySQL建表,字段需NULL時(shí),需設(shè)置字段默認(rèn)值,默認(rèn)值不為NULL。
三、 MySQL建表,如果字段等價(jià)于外鍵,應(yīng)在該字段加索引。
四、 MySQL建表,不同表之間的相同屬性值的字段,列類(lèi)型,類(lèi)型長(zhǎng)度,是否非空,是否默認(rèn)值,需保持一致,否則無(wú)法正確使用索引進(jìn)行關(guān)聯(lián)對(duì)比。
五、 MySQL使用時(shí),一條SQL語(yǔ)句只能使用一個(gè)表的一個(gè)索引。所有的字段類(lèi)型都可以索引,多列索引的屬性最多15個(gè)。
六、 如果可以在多個(gè)索引中進(jìn)行選擇,MySQL通常使用找到最少行的索引,索引唯一值最高的索引。
七、 建立索引index(part1,part2,part3),相當(dāng)于建立了 index(part1),index(part1,part2)和index(part1,part2,part3)三個(gè)索引。
八、 MySQL針對(duì)like語(yǔ)法必須如下格式才使用索引:
SELECT * FROM t1 WHERE key_col LIKE 'ab%' ;
九、 SELECT COUNT(*) 語(yǔ)法在沒(méi)有where條件的語(yǔ)句中執(zhí)行效率沒(méi)有SELECT COUNT(col_name)快,但是在有where條件的語(yǔ)句中執(zhí)行效率要快。
十、 在where條件中多個(gè)and的條件中,必須都是一個(gè)多列索引的key_part屬性而且必須包含key_part1。各自單一索引的話,只使用遍歷最少行的那個(gè)索引。
十一、 在where條件中多個(gè)or的條件中,每一個(gè)條件,都必須是一個(gè)有效索引。
十二、 ORDER BY 后面的條件必須是同一索引的屬性,排序順序必須一致(比如都是升序或都是降序)。
十三、 所有GROUP BY列引用同一索引的屬性,并且索引必須是按順序保存其關(guān)鍵字的。
十四、 JOIN 索引,所有匹配ON和where的字段應(yīng)建立合適的索引。
十五、 對(duì)智能的掃描全表使用FORCE INDEX告知MySQL,使用索引效率更高。
十六、 定期ANALYZE TABLE tbl_name為掃描的表更新關(guān)鍵字分布 。
十七、 定期使用慢日志檢查語(yǔ)句,執(zhí)行explain,分析可能改進(jìn)的索引。
十八、 條件允許的話,設(shè)置較大的key_buffer_size和query_cache_size的值(全局參數(shù)),和sort_buffer_size的值(session變量,建議不要超過(guò)4M)。
備注
主鍵的命名采用如下規(guī)則:
主鍵名用pk_開(kāi)頭,后面跟該主鍵所在的表名。主鍵名長(zhǎng)度不能超過(guò)30個(gè)字符。如果過(guò)長(zhǎng),可對(duì)表名進(jìn)行縮寫(xiě)。縮寫(xiě)規(guī)則同表名的縮寫(xiě)規(guī)則。主鍵名用小寫(xiě)的英文單詞來(lái)表示。
外鍵的命名采用如下規(guī)則:
外鍵名用fk_開(kāi)頭,后面跟該外鍵所在的表名和對(duì)應(yīng)的主表名(不含t_)。子表名和父表名自己用下劃線(_)分隔。外鍵名長(zhǎng)度不能超過(guò)30個(gè)字符。如果過(guò)長(zhǎng),可對(duì)表名進(jìn)行縮寫(xiě)。縮寫(xiě)規(guī)則同表名的縮寫(xiě)規(guī)則。外鍵名用小寫(xiě)的英文單詞來(lái)表示。
索引的命名采用如下規(guī)則:
1)索引名用小寫(xiě)的英文字母和數(shù)字表示。索引名的長(zhǎng)度不能超過(guò)30個(gè)字符。
2)主鍵對(duì)應(yīng)的索引和主鍵同名。
3)唯一性索引用uni_開(kāi)頭,后面跟表名。一般性索引用ind_開(kāi)頭,后面跟表名。
4)如果索引長(zhǎng)度過(guò)長(zhǎng),可對(duì)表名進(jìn)行縮寫(xiě)。縮寫(xiě)規(guī)則同表名的縮寫(xiě)規(guī)則
index 相關(guān)語(yǔ)法
例:
CREATE INDEX log_url ON logaudit_log(url);
show index from logaudit_log
drop index log_request_time on logaudit_log
sql執(zhí)行效率檢測(cè) mysql explain
explain顯示了mysql如何使用索引來(lái)處理select語(yǔ)句以及連接表。可以幫助選擇更好的索引和寫(xiě)出更優(yōu)化的查詢(xún)語(yǔ)句。
使用方法,在select語(yǔ)句前加上explain就可以了:
如:explain select surname,first_name form a,b where a.id=b.id
分析結(jié)果形式如下:
table | type | possible_keys | key | key_len | ref | rows | Extra
EXPLAIN列的解釋?zhuān)?br />table
顯示這一行的數(shù)據(jù)是關(guān)于哪張表的
type
這是重要的列,顯示連接使用了何種類(lèi)型。從最好到最差的連接類(lèi)型為const、eq_reg、ref、range、indexhe和ALL
possible_keys
顯示可能應(yīng)用在這張表中的索引。如果為空,沒(méi)有可能的索引。可以為相關(guān)的域從WHERE語(yǔ)句中選擇一個(gè)合適的語(yǔ)句
key
實(shí)際使用的索引。如果為NULL,則沒(méi)有使用索引。很少的情況下,MYSQL會(huì)選擇優(yōu)化不足的索引。這種情況下,可以在SELECT語(yǔ)句中使用USE
INDEX(indexname)來(lái)強(qiáng)制使用一個(gè)索引或者用IGNORE INDEX(indexname)來(lái)強(qiáng)制MYSQL忽略索引
key_len
使用的索引的長(zhǎng)度。在不損失精確性的情況下,長(zhǎng)度越短越好
ref
顯示索引的哪一列被使用了,如果可能的話,是一個(gè)常數(shù)
rows
MYSQL認(rèn)為必須檢查的用來(lái)返回請(qǐng)求數(shù)據(jù)的行數(shù)
Extra
關(guān)于MYSQL如何解析查詢(xún)的額外信息。將在表4.3中討論,但這里可以看到的壞的例子是Using temporary和Using filesort,意思MYSQL根本不能使用索引,結(jié)果是檢索會(huì)很慢
extra列返回的描述的意義
Distinct
一旦MYSQL找到了與行相聯(lián)合匹配的行,就不再搜索了
Not exists
MYSQL優(yōu)化了LEFT JOIN,一旦它找到了匹配LEFT JOIN標(biāo)準(zhǔn)的行,
就不再搜索了
Range checked for each
Record(index map:#)
沒(méi)有找到理想的索引,因此對(duì)于從前面表中來(lái)的每一個(gè)行組合,MYSQL檢查使用哪個(gè)索引,并用它來(lái)從表中返回行。這是使用索引的最慢的連接之一
Using filesort
看到這個(gè)的時(shí)候,查詢(xún)就需要優(yōu)化了。MYSQL需要進(jìn)行額外的步驟來(lái)發(fā)現(xiàn)如何對(duì)返回的行排序。它根據(jù)連接類(lèi)型以及存儲(chǔ)排序鍵值和匹配條件的全部行的行指針來(lái)排序全部行
Using index
列數(shù)據(jù)是從僅僅使用了索引中的信息而沒(méi)有讀取實(shí)際的行動(dòng)的表返回的,這發(fā)生在對(duì)表的全部的請(qǐng)求列都是同一個(gè)索引的部分的時(shí)候
Using temporary
看到這個(gè)的時(shí)候,查詢(xún)需要優(yōu)化了。這里,MYSQL需要?jiǎng)?chuàng)建一個(gè)臨時(shí)表來(lái)存儲(chǔ)結(jié)果,這通常發(fā)生在對(duì)不同的列集進(jìn)行ORDER BY上,而不是GROUP BY上
Where used
使用了WHERE從句來(lái)限制哪些行將與下一張表匹配或者是返回給用戶(hù)。如果不想返回表中的全部行,并且連接類(lèi)型ALL或index,這就會(huì)發(fā)生,或者是查詢(xún)有問(wèn)題
不同連接類(lèi)型的解釋?zhuān)ò凑招矢叩偷捻樞蚺判颍?br />system
表只有一行:system表。這是const連接類(lèi)型的特殊情況
const
表中的一個(gè)記錄的最大值能夠匹配這個(gè)查詢(xún)(索引可以是主鍵或惟一索引)。因?yàn)橹挥幸恍校@個(gè)值實(shí)際就是常數(shù),因?yàn)镸YSQL先讀這個(gè)值然后把它當(dāng)做常數(shù)來(lái)對(duì)待
eq_ref
在連接中,MYSQL在查詢(xún)時(shí),從前面的表中,對(duì)每一個(gè)記錄的聯(lián)合都從表中讀取一個(gè)記錄,它在查詢(xún)使用了索引為主鍵或惟一鍵的全部時(shí)使用
ref
這個(gè)連接類(lèi)型只有在查詢(xún)使用了不是惟一或主鍵的鍵或者是這些類(lèi)型的部分(比如,利用最左邊前綴)時(shí)發(fā)生。對(duì)于之前的表的每一個(gè)行聯(lián)合,全部記錄都將從表中讀出。這個(gè)類(lèi)型嚴(yán)重依賴(lài)于根據(jù)索引匹配的記錄多少—越少越好
range
這個(gè)連接類(lèi)型使用索引返回一個(gè)范圍中的行,比如使用>或
FAQ
1
表中包含 10 萬(wàn)條記錄,有一個(gè) datetime 類(lèi)型的字段。
取數(shù)據(jù)的語(yǔ)句:
SELECT * FROM my_table WHERE created_at < '2010-01-20';
用 EXPLAIN 檢查,發(fā)現(xiàn) type 是 ALL, key 是 NULL,根本沒(méi)用上索引。
可以確定的是,created_at 字段設(shè)定索引了。
什么原因呢?
用 SELECT COUNT(*) 看了一下符合 WHERE 條件的記錄總數(shù),居然是 6W 多條!!
難怪不用索引,這時(shí)用索引毫無(wú)意義,就好像 10 萬(wàn)條記錄的用戶(hù)表,有個(gè)性別字段,不是男就是女,在這種字段設(shè)置索引是錯(cuò)誤的決定。
稍微改造一下上述語(yǔ)句:
SELECT * FROM my_table WHERE created_at BETWEEN '2009-12-06' AND '2010-01-20';
這回問(wèn)題解決!
符合條件的記錄只有幾百條,EXPLAIN 的 type 是 range,key 是 created_at,Extra 是 Using where 。
自己總結(jié)個(gè)準(zhǔn)則,索引的目的就是盡量縮小結(jié)果集,這樣才能做到快速查詢(xún)。
6萬(wàn)條記錄符合條件,已經(jīng)超出總記錄數(shù)的一半,這時(shí)索引已經(jīng)沒(méi)有意義了,因此 MySQL 放棄使用索引。
這與設(shè)置 gender 字段,并加上索引的情況相似,當(dāng)你要把所有男性記錄都選取出來(lái),符合條件的記錄數(shù)約占總數(shù)的一半,MySQL 同樣不會(huì)使用這個(gè)索引。
唯一值越多的字段,使用索引的效果越好。
設(shè)置聯(lián)合索引時(shí),唯一值越多的,越應(yīng)該放在“左側(cè)”。
新聞熱點(diǎn)
疑難解答
圖片精選