數(shù)據(jù)庫設(shè)計(jì)總結(jié)
1.盡量避免過度設(shè)計(jì)祝懂,例如會(huì)導(dǎo)致及其復(fù)雜查詢的schema設(shè)計(jì)票摇,或者有很多列的表設(shè)計(jì)。
2.使用小而簡單的合適數(shù)據(jù)類型砚蓬,除非真實(shí)數(shù)據(jù)模型中有確切的需要矢门,否則應(yīng)該盡可能地避免使用NULL值。
3.盡量使用相同的數(shù)據(jù)類型存儲相似或相關(guān)的值灰蛙,尤其是需要在關(guān)聯(lián)條件中使用的列祟剔。
4.注意可變長字符串,其在臨時(shí)表和排序時(shí)可能導(dǎo)致悲觀的按最大長度分配內(nèi)存摩梧。
5.盡量使用整形定義標(biāo)識列物延。
6.避免使用MySQL已經(jīng)廢棄的特性,例如指定浮點(diǎn)數(shù)的精度等仅父。
7.小心使用ENUM和SET叛薯。雖然他們用起來很方便,但是不要濫用笙纤,否則有可能變成陷阱耗溜。
索引
BTree索引,是一種樹結(jié)構(gòu)省容,索引速度比全表查詢速度快强霎。
每個(gè)葉子節(jié)點(diǎn)即使MySQL中的一個(gè)頁,默認(rèn)每頁16KB大小蓉冈。
MySQL中InnoDB使用B+Tree城舞,B+Tree中每個(gè)葉子節(jié)點(diǎn)都有一個(gè)指向先一個(gè)葉子節(jié)點(diǎn)的指針。
組合索引
InnoDB中BTree索引生效的情況【customer創(chuàng)建組合索引(last_name, first_name, email)】
匹配最左前綴:查找姓為MILLER的人寞酿,只使用索引的第一列家夺。
explain select * from customer where last_name='MILLER';
全值匹配:全值匹配是指和索引中所有的列進(jìn)行匹配,例如查找姓名為MARIA MILLER伐弹,email為MARIA.MILLER@sakilacustomer.org的人拉馋。
explain select * from customer where last_name='MILLER' and first_name='MARIA' and email='MARIA.MILLER@sakilacustomer.org';
匹配列前綴:可以匹配某一列值的開頭部分,例如查找以M開頭的姓的人。
EXPLAIN select * from customer where last_name like 'M%';
匹配范圍值:查找姓大于等于WEINER的人煌茴。
EXPLAIN select * from customer where last_name>='WEINER';
精確匹配某一列并范圍匹配另一列:查找所有姓為MILLER随闺,且名字是字母M開頭的人。即第一列l(wèi)ast_name的全匹配蔓腐,第二列first_name范圍匹配矩乐。(也是前綴匹配)
EXPLAIN select * from customer where last_name='MILLER' and first_name like 'M%';
#如果不是按照索引的最左列開始查找,則無法使用索引【不從last_name列開始檢索】
explain select * from customer where first_name='MARIA' and email='MARIA.MILLER@sakilacustomer.org';
#不能跳過索引中的列【沒有first_name列】
explain select * from customer where last_name='MILLER' and email>'SHEILA.WELLS@sakilacustomer.org';
#如果查詢中有某個(gè)列的范圍查詢回论,則其右邊所有列都無法使用索引優(yōu)化查找【first_name為范圍查找散罕,email列無效】
explain select * from customer where last_name='MILLER' and first_name>'MARIA'
and email='MELANIE.ARMSTRONG@sakilacustomer.org';
Hash索引,在MySQL中只有Memory引擎支持
當(dāng)Hash索引中出現(xiàn)哈希沖突的時(shí)候傀蓉,存儲引擎需要遍歷鏈表中所有的行欧漱,找到所有符合條件的數(shù)據(jù)。
沖突越多葬燎,索引代價(jià)越大误甚。
<=> 并非 <>
Mysql 的 InnoDB引擎 有一個(gè)功能叫做“自適應(yīng)哈希索引”。當(dāng)MySQL發(fā)現(xiàn)某些索引值被頻繁使用時(shí)谱净,會(huì)在內(nèi)存中基于BTree索引創(chuàng)建一個(gè)哈希索引窑邦。整個(gè)過程無法認(rèn)為控制,僅可以通過innodb_adaptive_hash_index屬性配置是否開啟岳遥,默認(rèn)開啟該功能奕翔。
InnoDB聚簇索引(主鍵索引)
已滿的頁中,如果需要插入新的數(shù)據(jù)浩蓉,會(huì)導(dǎo)致頁分裂
InnoDB二級索引
Select id,name from tablename where name=’Rose’; #只需要遍歷二級索引即可得到結(jié)果派继。
Myisam引擎索引
Myisam引擎中,主鍵索引與其他索引在結(jié)構(gòu)上沒有區(qū)別捻艳。
InnoDB中默認(rèn)最大填充因子是頁的15/16大小 MySQL默認(rèn)每頁16K 數(shù)據(jù)達(dá)到15K的時(shí)候驾窟, 分配到下一頁。 不同頁之間可能不是順序的认轨,只是通過一個(gè)指針相連绅络。
InnoDB主鍵最好是連續(xù)遞增的值,盡量避免使用UUID之類的長而無需的字符串嘁字。使用UUID做主鍵恩急,在BTree的聚簇索引上,會(huì)導(dǎo)致插入速度慢纪蜒,索引空間更大衷恭,其他二級索引空間也會(huì)更大。
索引空間變大的原因有兩個(gè)纯续,一個(gè)是由于主鍵字段更長随珠,其次是因?yàn)轫摲至押退槠摬伙柡停?dǎo)致灭袁。
索引列的字段要盡可能小 因?yàn)锽Tree索引樹高度頁的大小以及頁里面的數(shù)據(jù)大小決定的。數(shù)據(jù)越小窗看,磁盤塊存儲的數(shù)據(jù)越多茸歧,樹的高度越低,查詢性能越高显沈。
三星索引:
1软瞎、索引將相關(guān)的記錄放到一起(Where子句后面的條件都可以使用索引,體現(xiàn)組合索引的利用)
2构罗、索引中數(shù)據(jù)的順序和查找中的排列順序一致(利用索引的有序性直接得到排序結(jié)果)
3铜涉、索引中的列包含了查詢中全部需要的列(利用索引中的值智玻,直接得到查詢結(jié)果遂唧,避免回表)