Mysql建表與索引使用規(guī)范詳解
一、 MySQL建表,字段需設(shè)置為非空,需設(shè)置字段默認(rèn)值。
二、 MySQL建表,字段需NULL時,需設(shè)置字段默認(rèn)值,默認(rèn)值不為NULL。
三、 MySQL建表,如果字段等價于外鍵,應(yīng)在該字段加索引。
四、 MySQL建表,不同表之間的相同屬性值的字段,列類型,類型長度,是否非空,是否默認(rèn)值,需保持一致,否則無法正確使用索引進(jìn)行關(guān)聯(lián)對比。
五、 MySQL使用時,一條SQL語句只能使用一個表的一個索引。所有的字段類型都可以索引,多列索引的屬性最多15個。
六、 如果可以在多個索引中進(jìn)行選擇,MySQL通常使用找到最少行的索引,索引唯一值最高的索引。
七、 建立索引index(part1,part2,part3),相當(dāng)于建立了 index(part1),index(part1,part2)和index(part1,part2,part3)三個索引。
八、 MySQL針對like語法必須如下格式才使用索引:
SELECT * FROM t1 WHERE key_col LIKE 'ab%' ;
九、 SELECT COUNT(*) 語法在沒有where條件的語句中執(zhí)行效率沒有SELECT COUNT(col_name)快,但是在有where條件的語句中執(zhí)行效率要快。
十、 在where條件中多個and的條件中,必須都是一個多列索引的key_part屬性而且必須包含key_part1。各自單一索引的話,只使用遍歷最少行的那個索引。
十一、 在where條件中多個or的條件中,每一個條件,都必須是一個有效索引。
十二、 ORDER BY 后面的條件必須是同一索引的屬性,排序順序必須一致(比如都是升序或都是降序)。
十三、 所有GROUP BY列引用同一索引的屬性,并且索引必須是按順序保存其關(guān)鍵字的。
十四、 JOIN 索引,所有匹配ON和where的字段應(yīng)建立合適的索引。
十五、 對智能的掃描全表使用FORCE INDEX告知MySQL,使用索引效率更高。
十六、 定期ANALYZE TABLE tbl_name為掃描的表更新關(guān)鍵字分布 。
十七、 定期使用慢日志檢查語句,執(zhí)行explain,分析可能改進(jìn)的索引。
十八、 條件允許的話,設(shè)置較大的key_buffer_size和query_cache_size的值(全局參數(shù)),和sort_buffer_size的值(session變量,建議不要超過4M)。
備注
主鍵的命名采用如下規(guī)則:
主鍵名用pk_開頭,后面跟該主鍵所在的表名。主鍵名長度不能超過30個字符。如果過長,可對表名進(jìn)行縮寫??s寫規(guī)則同表名的縮寫規(guī)則。主鍵名用小寫的英文單詞來表示。
外鍵的命名采用如下規(guī)則:
外鍵名用fk_開頭,后面跟該外鍵所在的表名和對應(yīng)的主表名(不含t_)。子表名和父表名自己用下劃線(_)分隔。外鍵名長度不能超過30個字符。如果過長,可對表名進(jìn)行縮寫。縮寫規(guī)則同表名的縮寫規(guī)則。外鍵名用小寫的英文單詞來表示。
索引的命名采用如下規(guī)則:
1)索引名用小寫的英文字母和數(shù)字表示。索引名的長度不能超過30個字符。
2)主鍵對應(yīng)的索引和主鍵同名。
3)唯一性索引用uni_開頭,后面跟表名。一般性索引用ind_開頭,后面跟表名。
4)如果索引長度過長,可對表名進(jìn)行縮寫??s寫規(guī)則同表名的縮寫規(guī)則
index 相關(guān)語法
例:
CREATE INDEX log_url ON logaudit_log(url);
show index from logaudit_log
drop index log_request_time on logaudit_log
sql執(zhí)行效率檢測 mysql explain
explain顯示了mysql如何使用索引來處理select語句以及連接表。可以幫助選擇更好的索引和寫出更優(yōu)化的查詢語句。
使用方法,在select語句前加上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列的解釋:
table
顯示這一行的數(shù)據(jù)是關(guān)于哪張表的
type
這是重要的列,顯示連接使用了何種類型。從最好到最差的連接類型為const、eq_reg、ref、range、indexhe和ALL
possible_keys
顯示可能應(yīng)用在這張表中的索引。如果為空,沒有可能的索引??梢詾橄嚓P(guān)的域從WHERE語句中選擇一個合適的語句
key
實際使用的索引。如果為NULL,則沒有使用索引。很少的情況下,MYSQL會選擇優(yōu)化不足的索引。這種情況下,可以在SELECT語句中使用USE
INDEX(indexname)來強制使用一個索引或者用IGNORE INDEX(indexname)來強制MYSQL忽略索引
key_len
使用的索引的長度。在不損失精確性的情況下,長度越短越好
ref
顯示索引的哪一列被使用了,如果可能的話,是一個常數(shù)
rows
MYSQL認(rèn)為必須檢查的用來返回請求數(shù)據(jù)的行數(shù)
Extra
關(guān)于MYSQL如何解析查詢的額外信息。將在表4.3中討論,但這里可以看到的壞的例子是Using temporary和Using filesort,意思MYSQL根本不能使用索引,結(jié)果是檢索會很慢
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:#)
沒有找到理想的索引,因此對于從前面表中來的每一個行組合,MYSQL檢查使用哪個索引,并用它來從表中返回行。這是使用索引的最慢的連接之一
Using filesort
看到這個的時候,查詢就需要優(yōu)化了。MYSQL需要進(jìn)行額外的步驟來發(fā)現(xiàn)如何對返回的行排序。它根據(jù)連接類型以及存儲排序鍵值和匹配條件的全部行的行指針來排序全部行
Using index
列數(shù)據(jù)是從僅僅使用了索引中的信息而沒有讀取實際的行動的表返回的,這發(fā)生在對表的全部的請求列都是同一個索引的部分的時候
Using temporary
看到這個的時候,查詢需要優(yōu)化了。這里,MYSQL需要創(chuàng)建一個臨時表來存儲結(jié)果,這通常發(fā)生在對不同的列集進(jìn)行ORDER BY上,而不是GROUP BY上
Where used
使用了WHERE從句來限制哪些行將與下一張表匹配或者是返回給用戶。如果不想返回表中的全部行,并且連接類型ALL或index,這就會發(fā)生,或者是查詢有問題
不同連接類型的解釋(按照效率高低的順序排序)
system
表只有一行:system表。這是const連接類型的特殊情況
const
表中的一個記錄的最大值能夠匹配這個查詢(索引可以是主鍵或惟一索引)。因為只有一行,這個值實際就是常數(shù),因為MYSQL先讀這個值然后把它當(dāng)做常數(shù)來對待
eq_ref
在連接中,MYSQL在查詢時,從前面的表中,對每一個記錄的聯(lián)合都從表中讀取一個記錄,它在查詢使用了索引為主鍵或惟一鍵的全部時使用
ref
這個連接類型只有在查詢使用了不是惟一或主鍵的鍵或者是這些類型的部分(比如,利用最左邊前綴)時發(fā)生。對于之前的表的每一個行聯(lián)合,全部記錄都將從表中讀出。這個類型嚴(yán)重依賴于根據(jù)索引匹配的記錄多少—越少越好
range
這個連接類型使用索引返回一個范圍中的行,比如使用>或
FAQ
1
表中包含 10 萬條記錄,有一個 datetime 類型的字段。
取數(shù)據(jù)的語句:
SELECT * FROM my_table WHERE created_at < '2010-01-20';
用 EXPLAIN 檢查,發(fā)現(xiàn) type 是 ALL, key 是 NULL,根本沒用上索引。
可以確定的是,created_at 字段設(shè)定索引了。
什么原因呢?
用 SELECT COUNT(*) 看了一下符合 WHERE 條件的記錄總數(shù),居然是 6W 多條??!
難怪不用索引,這時用索引毫無意義,就好像 10 萬條記錄的用戶表,有個性別字段,不是男就是女,在這種字段設(shè)置索引是錯誤的決定。
稍微改造一下上述語句:
SELECT * FROM my_table WHERE created_at BETWEEN '2009-12-06' AND '2010-01-20';
這回問題解決!
符合條件的記錄只有幾百條,EXPLAIN 的 type 是 range,key 是 created_at,Extra 是 Using where 。
自己總結(jié)個準(zhǔn)則,索引的目的就是盡量縮小結(jié)果集,這樣才能做到快速查詢。
6萬條記錄符合條件,已經(jīng)超出總記錄數(shù)的一半,這時索引已經(jīng)沒有意義了,因此 MySQL 放棄使用索引。
這與設(shè)置 gender 字段,并加上索引的情況相似,當(dāng)你要把所有男性記錄都選取出來,符合條件的記錄數(shù)約占總數(shù)的一半,MySQL 同樣不會使用這個索引。
唯一值越多的字段,使用索引的效果越好。
設(shè)置聯(lián)合索引時,唯一值越多的,越應(yīng)該放在“左側(cè)”。
相關(guān)文章
如何把本地mysql遷移到服務(wù)器數(shù)據(jù)庫
這篇文章主要介紹了如何把本地mysql遷移到服務(wù)器數(shù)據(jù)庫,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-11-11mysql行鎖(for update)解決高并發(fā)問題
這篇文章主要介紹了mysql行鎖(for update)解決高并發(fā)問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-08-08MySQL中對查詢結(jié)果排序和限定結(jié)果的返回數(shù)量的用法教程
這篇文章主要介紹了MySQL中對查詢結(jié)果排序和限定結(jié)果的返回數(shù)量的用法教程,分別講解了Order By語句和Limit語句的基本使用方法,需要的朋友可以參考下2015-12-12Mysql數(shù)據(jù)類型與CRUD操作詳細(xì)講解
這篇文章主要介紹了Mysql數(shù)據(jù)類型與CRUD操作,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-10-10