一庞呕、事務(wù)
四大特性(ACID)
- 原子性
根據(jù)定義,原子性是指一個(gè)事務(wù)是一個(gè)不可分割的工作單位程帕,其中的操作要么都做千扶,要么都不做。即要么轉(zhuǎn)賬成功骆捧,要么轉(zhuǎn)賬失敗,是不存在中間的狀態(tài)髓绽! - 一致性
根據(jù)定義敛苇,一致性是指事務(wù)執(zhí)行前后,數(shù)據(jù)處于一種合法的狀態(tài)顺呕,這種狀態(tài)是語(yǔ)義上的而不是語(yǔ)法上的枫攀。 - 隔離性
根據(jù)定義,隔離性是指多個(gè)事務(wù)并發(fā)執(zhí)行的時(shí)候株茶,事務(wù)內(nèi)部的操作與其他事務(wù)是隔離的来涨,并發(fā)執(zhí)行的各個(gè)事務(wù)之間不能互相干擾。
4启盛、持久性
根據(jù)定義蹦掐,持久性是指事務(wù)一旦提交,它對(duì)數(shù)據(jù)庫(kù)的改變就應(yīng)該是永久性的僵闯。接下來(lái)的其他操作或故障不應(yīng)該對(duì)其有任何影響卧抗。
隔離級(jí)別引發(fā)的問(wèn)題
- 臟讀
臟讀是指在一個(gè)事務(wù)處理過(guò)程里讀取了另一個(gè)未提交的事務(wù)中的數(shù)據(jù)。
當(dāng)一個(gè)事務(wù)正在多次修改某個(gè)數(shù)據(jù)鳖粟,而在這個(gè)事務(wù)中這多次的修改都還未提交社裆,這時(shí)一個(gè)并發(fā)的事務(wù)來(lái)訪問(wèn)該數(shù)據(jù),就會(huì)造成兩個(gè)事務(wù)得到的數(shù)據(jù)不一致向图。
舉個(gè)例子泳秀,A在一個(gè)轉(zhuǎn)賬事務(wù)中标沪,轉(zhuǎn)了100塊錢(qián)給B,此時(shí)B讀到了這個(gè)轉(zhuǎn)賬的數(shù)據(jù)嗜傅,然后做了一些操作(發(fā)貨給A金句,或者其他的),可是這時(shí)候A的事務(wù)并沒(méi)有提交磺陡,如果A回滾了事務(wù)趴梢,那就GG了。這就是臟讀了币他。 - 不可重復(fù)讀
不可重復(fù)讀是指在對(duì)于數(shù)據(jù)庫(kù)中的某個(gè)數(shù)據(jù)坞靶,一個(gè)事務(wù)范圍內(nèi)多次查詢卻返回了不同的數(shù)據(jù)值,這是由于在查詢間隔蝴悉,被另一個(gè)事務(wù)修改并提交了彰阴。
例如事務(wù)T1在讀取某一數(shù)據(jù),而事務(wù)T2立馬修改了這個(gè)數(shù)據(jù)并且提交事務(wù)給數(shù)據(jù)庫(kù)拍冠,事務(wù)T1再次讀取該數(shù)據(jù)就得到了不同的結(jié)果尿这,發(fā)送了不可重復(fù)讀。
不可重復(fù)讀和臟讀的區(qū)別是庆杜,臟讀是某一事務(wù)讀取了另一個(gè)事務(wù)未提交的臟數(shù)據(jù)射众,而不可重復(fù)讀則是讀取了前一事務(wù)提交的數(shù)據(jù)。
在某些情況下晃财,不可重復(fù)讀并不是問(wèn)題叨橱,比如我們多次查詢某個(gè)數(shù)據(jù)當(dāng)然以最后查詢得到的結(jié)果為主。但在另一些情況下就有可能發(fā)生問(wèn)題断盛,例如對(duì)于同一個(gè)數(shù)據(jù)A和B依次查詢就可能不同罗洗,A和B就可能打起來(lái)了…… - 幻讀
幻讀是事務(wù)非獨(dú)立執(zhí)行時(shí)發(fā)生的一種現(xiàn)象。例如事務(wù)T1對(duì)一個(gè)表中所有的行的某個(gè)數(shù)據(jù)項(xiàng)做了從“1”修改為“2”的操作钢猛,這時(shí)事務(wù)T2又對(duì)這個(gè)表中插入了一行數(shù)據(jù)項(xiàng)伙菜,而這個(gè)數(shù)據(jù)項(xiàng)的數(shù)值還是為“1”并且提交給數(shù)據(jù)庫(kù)。而操作事務(wù)T1的用戶如果再查看剛剛修改的數(shù)據(jù)命迈,會(huì)發(fā)現(xiàn)還有一行沒(méi)有修改贩绕,其實(shí)這行是從事務(wù)T2中添加的,就好像產(chǎn)生幻覺(jué)一樣躺翻,這就是發(fā)生了幻讀丧叽。
幻讀和不可重復(fù)讀都是讀取了另一條已經(jīng)提交的事務(wù)(這點(diǎn)就臟讀不同),所不同的是不可重復(fù)讀查詢的都是同一個(gè)數(shù)據(jù)項(xiàng)公你,而幻讀針對(duì)的是一批數(shù)據(jù)整體(比如數(shù)據(jù)的個(gè)數(shù))踊淳。
MySQL數(shù)據(jù)庫(kù)的四種隔離級(jí)別:
① Serializable (串行化):可避免臟讀、不可重復(fù)讀、幻讀的發(fā)生迂尝。
⊥衍浴② Repeatable read (可重復(fù)讀):可避免臟讀、不可重復(fù)讀的發(fā)生垄开。
∏傩怼③ Read committed (讀已提交):可避免臟讀的發(fā)生。
「榷恪④ Read uncommitted (讀未提交):最低級(jí)別榜田,任何情況都無(wú)法保證。
以上四種隔離級(jí)別最高的是Serializable級(jí)別锻梳,最低的是Read uncommitted級(jí)別箭券,當(dāng)然級(jí)別越高,執(zhí)行效率就越低疑枯。像Serializable這樣的級(jí)別辩块,就是以鎖表的方式(類(lèi)似于Java多線程中的鎖)使得其他的線程只能在鎖外等待,所以平時(shí)選用何種隔離級(jí)別應(yīng)該根據(jù)實(shí)際情況荆永。在MySQL數(shù)據(jù)庫(kù)中默認(rèn)的隔離級(jí)別為Repeatable read (可重復(fù)讀)废亭。
在MySQL數(shù)據(jù)庫(kù)中,支持上面四種隔離級(jí)別具钥,默認(rèn)的為Repeatable read (可重復(fù)讀)豆村;而在Oracle數(shù)據(jù)庫(kù)中,只支持Serializable (串行化)級(jí)別和Read committed (讀已提交)這兩種級(jí)別骂删,其中默認(rèn)的為Read committed級(jí)別你画。
mysql 查詢事務(wù)的隔離級(jí)別
select @@tx_isolation;
在MySQL數(shù)據(jù)庫(kù)中設(shè)置事務(wù)的隔離 級(jí)別:
set [glogal | session] transaction isolation level 隔離級(jí)別名稱;
set tx_isolation=’隔離級(jí)別名稱;’
二、MySQL常見(jiàn)的三種存儲(chǔ)引擎(InnoDB桃漾、MyISAM、MEMORY)
InnoDB:支持事務(wù)處理拟逮,支持外鍵撬统,支持崩潰修復(fù)能力和并發(fā)控制。如果需要對(duì)事務(wù)的完整性要求比較高(比如銀行)敦迄,要求實(shí)現(xiàn)并發(fā)控制(比如售票)恋追,那選擇InnoDB有很大的優(yōu)勢(shì)。如果需要頻繁的更新罚屋、刪除操作的數(shù)據(jù)庫(kù)苦囱,也可以選擇InnoDB,因?yàn)橹С质聞?wù)的提交(commit)和回滾(rollback)脾猛。
MyISAM:插入數(shù)據(jù)快撕彤,空間和內(nèi)存使用比較低。如果表主要是用于插入新記錄和讀出記錄,那么選擇MyISAM能實(shí)現(xiàn)處理高效率羹铅。如果應(yīng)用的完整性蚀狰、并發(fā)性要求比 較低,也可以使用职员。
MEMORY:所有的數(shù)據(jù)都在內(nèi)存中麻蹋,數(shù)據(jù)的處理速度快,但是安全性不高焊切。如果需要很快的讀寫(xiě)速度扮授,對(duì)數(shù)據(jù)的安全性要求較低,可以選擇MEMOEY专肪。它對(duì)表的大小有要求刹勃,不能建立太大的表。所以牵祟,這類(lèi)數(shù)據(jù)庫(kù)只使用在相對(duì)較小的數(shù)據(jù)庫(kù)表深夯。
MyISAM與InnoDB特點(diǎn)
MyISAM特點(diǎn)
不支持行鎖(MyISAM只有表鎖),讀取時(shí)對(duì)需要讀到的所有表加鎖诺苹,寫(xiě)入時(shí)則對(duì)表加排他鎖咕晋;
不支持事務(wù)
不支持外鍵
不支持崩潰后的安全恢復(fù)
在表有讀取查詢的同時(shí),支持往表中插入新紀(jì)錄
支持BLOB和TEXT的前500個(gè)字符索引收奔,支持全文索引
支持延遲更新索引掌呜,極大地提升了寫(xiě)入性能
對(duì)于不會(huì)進(jìn)行修改的表,支持 壓縮表 坪哄,極大地減少了磁盤(pán)空間的占用
InnoDB特點(diǎn)
支持行鎖质蕉,采用MVCC(Mutil-Version Concurrency Control),就是多版本并發(fā)控制翩肌,來(lái)支持高并發(fā)模暗,有可能死鎖
支持事務(wù)
支持外鍵
支持崩潰后的安全恢復(fù)
不支持全文索引
MyISAM和InnoDB兩者的應(yīng)用場(chǎng)景:
- MyISAM管理非事務(wù)表。它提供高速存儲(chǔ)和檢索念祭,以及全文搜索能力兑宇。如果應(yīng)用中需要執(zhí)行大量的SELECT查詢,那么MyISAM是更好的選擇粱坤。
- InnoDB用于事務(wù)處理應(yīng)用程序隶糕,具有眾多特性,包括ACID事務(wù)支持站玄。如果應(yīng)用中需要執(zhí)行大量的INSERT或UPDATE操作枚驻,則應(yīng)該使用InnoDB,這樣可以提高多用戶并發(fā)操作的性能株旷。
但是實(shí)際場(chǎng)景中再登,針對(duì)具體問(wèn)題需要具體分析,一般而言可以遵循以下幾個(gè)問(wèn)題:
- 數(shù)據(jù)庫(kù)是否有外鍵?
- 是否需要事務(wù)支持霎冯?
- 是否需要全文索引铃拇?
- 數(shù)據(jù)庫(kù)經(jīng)常使用什么樣的查詢模式?在寫(xiě)多讀少的應(yīng)用中還是Innodb插入性能更穩(wěn)定沈撞,在并發(fā)情況下也能基本慷荔,如果是對(duì)讀取速度要求比較快的應(yīng)用還是選MyISAM。
- 數(shù)據(jù)庫(kù)的數(shù)據(jù)有多大缠俺? 大尺寸傾向于innodb显晶,因?yàn)槭聞?wù)日志,故障恢復(fù)壹士。
InnoDB和MyISAM區(qū)別
- InnoDB支持事務(wù)磷雇,MyISAM不支持,對(duì)于InnoDB每一條SQL語(yǔ)言都默認(rèn)封裝成事務(wù)躏救,自動(dòng)提交唯笙,這樣會(huì)影響速度,所以最好把多條SQL語(yǔ)言放在begin和commit之間盒使,組成一個(gè)事務(wù)崩掘;
- InnoDB支持外鍵,而MyISAM不支持少办。對(duì)一個(gè)包含外鍵的InnoDB表轉(zhuǎn)為MYISAM會(huì)失敯;
- InnoDB是聚集索引英妓,使用B+Tree作為索引結(jié)構(gòu)挽放,數(shù)據(jù)文件是和(主鍵)索引綁在一起的(表數(shù)據(jù)文件本身就是按B+Tree組織的一個(gè)索引結(jié)構(gòu)),必須要有主鍵蔓纠,通過(guò)主鍵索引效率很高辑畦。但是輔助索引需要兩次查詢,先查詢到主鍵腿倚,然后再通過(guò)主鍵查詢到數(shù)據(jù)航闺。因此,主鍵不應(yīng)該過(guò)大猴誊,因?yàn)橹麈I太大,其他索引也都會(huì)很大侮措。
MyISAM是非聚集索引懈叹,也是使用B+Tree作為索引結(jié)構(gòu),索引和數(shù)據(jù)文件是分離的分扎,索引保存的是數(shù)據(jù)文件的指針澄成。主鍵索引和輔助索引是獨(dú)立的。
也就是說(shuō):InnoDB的B+樹(shù)主鍵索引的葉子節(jié)點(diǎn)就是數(shù)據(jù)文件,輔助索引的葉子節(jié)點(diǎn)是主鍵的值墨状;而MyISAM的B+樹(shù)主鍵索引和輔助索引的葉子節(jié)點(diǎn)都是數(shù)據(jù)文件的地址指針卫漫。 - InnoDB不保存表的具體行數(shù),執(zhí)行select count(*) from table時(shí)需要全表掃描肾砂。而MyISAM用一個(gè)變量保存了整個(gè)表的行數(shù)列赎,執(zhí)行上述語(yǔ)句時(shí)只需要讀出該變量即可,速度很快(注意不能加有任何WHERE條件)镐确;
那么為什么InnoDB沒(méi)有了這個(gè)變量呢包吝?
因?yàn)镮nnoDB的事務(wù)特性,在同一時(shí)刻表中的行數(shù)對(duì)于不同的事務(wù)而言是不一樣的源葫,因此count統(tǒng)計(jì)會(huì)計(jì)算對(duì)于當(dāng)前事務(wù)而言可以統(tǒng)計(jì)到的行數(shù)诗越,而不是將總行數(shù)儲(chǔ)存起來(lái)方便快速查詢。InnoDB會(huì)嘗試遍歷一個(gè)盡可能小的索引除非優(yōu)化器提示使用別的索引息堂。如果二級(jí)索引不存在嚷狞,InnoDB還會(huì)嘗試去遍歷其他聚簇索引。
如果索引并沒(méi)有完全處于InnoDB維護(hù)的緩沖區(qū)(Buffer Pool)中荣堰,count操作會(huì)比較費(fèi)時(shí)床未。可以建立一個(gè)記錄總行數(shù)的表并讓你的程序在INSERT/DELETE時(shí)更新對(duì)應(yīng)的數(shù)據(jù)持隧。和上面提到的問(wèn)題一樣即硼,如果此時(shí)存在多個(gè)事務(wù)的話這種方案也不太好用。如果得到大致的行數(shù)值已經(jīng)足夠滿足需求可以嘗試SHOW TABLE STATUS - Innodb不支持全文索引屡拨,而MyISAM支持全文索引只酥,在涉及全文索引領(lǐng)域的查詢效率上MyISAM速度更快高;PS:5.7以后的InnoDB支持全文索引了
- MyISAM表格可以被壓縮后進(jìn)行查詢操作
- InnoDB支持表呀狼、行(默認(rèn))級(jí)鎖裂允,而MyISAM支持表級(jí)鎖
InnoDB的行鎖是實(shí)現(xiàn)在索引上的,而不是鎖在物理行記錄上哥艇。潛臺(tái)詞是绝编,如果訪問(wèn)沒(méi)有命中索引,也無(wú)法使用行鎖貌踏,將要退化為表鎖十饥。
8、InnoDB表必須有唯一索引(如主鍵)(用戶沒(méi)有指定的話會(huì)自己找/生產(chǎn)一個(gè)隱藏列Row_id來(lái)充當(dāng)默認(rèn)主鍵)祖乳,而Myisam可以沒(méi)有
9逗堵、Innodb存儲(chǔ)文件有frm、ibd眷昆,而Myisam是frm蜒秤、MYD汁咏、MYI
Innodb:frm是表定義文件,ibd是數(shù)據(jù)文件
Myisam:frm是表定義文件作媚,myd是數(shù)據(jù)文件攘滩,myi是索引文件
如何選擇:
1. 是否要支持事務(wù),如果要請(qǐng)選擇innodb纸泡,如果不需要可以考慮MyISAM漂问;
2. 如果表中絕大多數(shù)都只是讀查詢,可以考慮MyISAM弟灼,如果既有讀也有寫(xiě)级解,請(qǐng)使用InnoDB。
3. 系統(tǒng)奔潰后田绑,MyISAM恢復(fù)起來(lái)更困難勤哗,能否接受;
4. MySQL5.5版本開(kāi)始Innodb已經(jīng)成為Mysql的默認(rèn)引擎(之前是MyISAM)掩驱,說(shuō)明其優(yōu)勢(shì)是有目共睹的芒划,如果你不知道用什么,那就用InnoDB欧穴,至少不會(huì)差民逼。
InnoDB為什么推薦使用自增ID作為主鍵?
答:自增ID可以保證每次插入時(shí)B+索引是從右邊擴(kuò)展的涮帘,可以避免B+樹(shù)和頻繁合并和分裂(對(duì)比使用UUID)拼苍。如果使用字符串主鍵和隨機(jī)主鍵,會(huì)使得數(shù)據(jù)隨機(jī)插入调缨,效率比較差疮鲫。
innodb引擎的4大特性
插入緩沖(insert buffer),二次寫(xiě)(double write),自適應(yīng)哈希索引(ahi),預(yù)讀(read ahead)
三、SQL執(zhí)行順序
1弦叶、from 子句組裝來(lái)自不同數(shù)據(jù)源的數(shù)據(jù)俊犯;
2、where 子句基于指定的條件對(duì)記錄行進(jìn)行篩選伤哺;
3燕侠、group by 子句將數(shù)據(jù)劃分為多個(gè)分組;
4立莉、使用聚集函數(shù)進(jìn)行計(jì)算绢彤;
5、使用 having 子句篩選分組蜓耻;
6茫舶、計(jì)算所有的表達(dá)式;
7媒熊、select 的字段奇适;
8、使用 order by 對(duì)結(jié)果集進(jìn)行排序芦鳍。
四嚷往、臨時(shí)表
MySQL用于存儲(chǔ)一些中間結(jié)果集的表,臨時(shí)表只在當(dāng)前連接可見(jiàn)柠衅,當(dāng)關(guān)閉連接時(shí)皮仁,Mysql會(huì)自動(dòng)刪除表并釋放所有空間。為什么會(huì)產(chǎn)生臨時(shí)表:一般是由于復(fù)雜的SQL導(dǎo)致臨時(shí)表被大量創(chuàng)建菲宴。
內(nèi)存臨時(shí)表空間的大小由兩個(gè)參數(shù)控制:tmp_table_size贷祈,max_heap_table_size。
下列操作會(huì)使用到內(nèi)存臨時(shí)表:
union查詢
對(duì)于視圖的操作喝峦,比如使用一些TEMPTABLE算法势誊、union或aggregation
子查詢
join 包括not in、exist等
查詢產(chǎn)生的派生表
復(fù)雜的group by 和 order by
Insert select 同一個(gè)表谣蠢,mysql會(huì)產(chǎn)生一個(gè)臨時(shí)表緩存select的行
多個(gè)表更新
GROUP_CONCAT() 或者 COUNT(DISTINCT) 語(yǔ)句
Mysql還會(huì)阻止內(nèi)存表空間的使用粟耻,直接使用磁盤(pán)臨時(shí)表:
表中含有BLOB或者TEXT列
使用union或者union all時(shí),select子句有大于512字節(jié)的列
Show columns或者 desc 表的時(shí)候眉踱,有LOB或者TEXT
GROUP BY 或者 DISTINCT 子句中包含長(zhǎng)度大于512字節(jié)的列
五. MySQL B+Tree索引和Hash索引的區(qū)別挤忙?
(1)Hash 索引僅僅能滿足"=","IN"和"<=>"查詢,不能使用范圍查詢谈喳。
由于 Hash 索引比較的是進(jìn)行 Hash 運(yùn)算之后的 Hash 值册烈,所以它只能用于等值的過(guò)濾,不能用于基于范圍的過(guò)濾婿禽,因?yàn)榻?jīng)過(guò)相應(yīng)的 Hash 算法處理之后的 Hash 值的大小關(guān)系赏僧,并不能保證和Hash運(yùn)算前完全一樣。
(2)Hash 索引無(wú)法被用來(lái)避免數(shù)據(jù)的排序操作谈宛。
由于 Hash 索引中存放的是經(jīng)過(guò) Hash 計(jì)算之后的 Hash 值次哈,而且Hash值的大小關(guān)系并不一定和 Hash 運(yùn)算前的鍵值完全一樣,所以數(shù)據(jù)庫(kù)無(wú)法利用索引的數(shù)據(jù)來(lái)避免任何排序運(yùn)算吆录;
(3)Hash 索引不能利用部分索引鍵查詢窑滞。
對(duì)于組合索引,Hash 索引在計(jì)算 Hash 值的時(shí)候是組合索引鍵合并后再一起計(jì)算 Hash 值恢筝,而不是單獨(dú)計(jì)算 Hash 值哀卫,所以通過(guò)組合索引的前面一個(gè)或幾個(gè)索引鍵進(jìn)行查詢的時(shí)候,Hash 索引也無(wú)法被利用撬槽。
(4)Hash 索引在任何時(shí)候都不能避免表掃描此改。
前面已經(jīng)知道,Hash 索引是將索引鍵通過(guò) Hash 運(yùn)算之后侄柔,將 Hash運(yùn)算結(jié)果的 Hash 值和所對(duì)應(yīng)的行指針信息存放于一個(gè) Hash 表中共啃,由于不同索引鍵存在相同 Hash 值占调,所以即使取滿足某個(gè) Hash 鍵值的數(shù)據(jù)的記錄條數(shù),也無(wú)法從 Hash 索引中直接完成查詢移剪,還是要通過(guò)訪問(wèn)表中的實(shí)際數(shù)據(jù)進(jìn)行相應(yīng)的比較究珊,并得到相應(yīng)的結(jié)果。
(5)Hash 索引遇到大量Hash值相等的情況后性能并不一定就會(huì)比B-Tree索引高纵苛。
六剿涮、聚集索引和非聚集索引的概念區(qū)別
聚簇索引(主鍵索引)
1.使用記錄主鍵值的大小來(lái)進(jìn)行記錄和頁(yè)的排序。
頁(yè)內(nèi)的記錄是按照主鍵的大小順序排成一個(gè)單項(xiàng)鏈表攻人。
各個(gè)存放用戶記錄的頁(yè)也是根據(jù)頁(yè)中用戶記錄的主鍵大小順序排成一個(gè)雙向鏈表取试。
2.葉子節(jié)點(diǎn)存儲(chǔ)的是完整的用戶記錄。
非聚簇索引(二級(jí)索引)
1.葉子節(jié)點(diǎn)內(nèi)部使用name字段排序怀吻,葉子節(jié)點(diǎn)之間也是使用name字段排序瞬浓。
2.葉子節(jié)點(diǎn)不再是完整的數(shù)據(jù)記錄,而是name和主鍵值烙博。
區(qū)別:
1瑟蜈、聚集索引一個(gè)表只能有一個(gè),而非聚集索引一個(gè)表可以存在多個(gè)
2渣窜、聚集索引存儲(chǔ)記錄是物理上連續(xù)存在铺根,而非聚集索引是邏輯上的連續(xù),物理存儲(chǔ)并不連續(xù)乔宿。
PS:
聯(lián)合索引
如果name和age組成一個(gè)聯(lián)合索引位迂,那么先按name排序,如果name一樣详瑞,就按age排序掂林。
索引使用原則
1.最左前綴原則。一個(gè)聯(lián)合索引(a,b,c),如果有一個(gè)查詢條件有a坝橡,有b泻帮,那么他則走索引,如果有一個(gè)查詢條件沒(méi)有a计寇,那么他則不走索引锣杂。
2.使用唯一索引。具有多個(gè)重復(fù)值的列番宁,其索引效果最差元莫。例如,存放姓名的列具有不同值蝶押,很容易區(qū)分每行踱蠢。而用來(lái)記錄性別的列,只含有“男”棋电,“女”茎截,不管搜索哪個(gè)值苇侵,都會(huì)得出大約一半的行,這樣的索引對(duì)性能的提升不夠高企锌。
3.不要過(guò)度索引衅檀。每個(gè)額外的索引都要占用額外的磁盤(pán)空間,并降低寫(xiě)操作的性能霎俩。在修改表的內(nèi)容時(shí),索引必須進(jìn)行更新沉眶,有時(shí)可能需要重構(gòu)打却,因此,索引越多谎倔,所花的時(shí)間越長(zhǎng)柳击。
4、索引列不能參與計(jì)算片习,保持列“干凈”捌肴,比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,原因很簡(jiǎn)單藕咏,b+樹(shù)中存的都是數(shù)據(jù)表中的字段值状知,但進(jìn)行檢索時(shí),需要把所有元素都應(yīng)用函數(shù)才能比較孽查,顯然成本太大饥悴。所以語(yǔ)句應(yīng)該寫(xiě)成create_time = unix_timestamp(’2014-05-29’);
5.一定要設(shè)置一個(gè)主鍵。前面聚簇索引說(shuō)到如果不指定主鍵盲再,InnoDB會(huì)自動(dòng)為其指定主鍵西设,這個(gè)我們是看不見(jiàn)的。反正都要生成一個(gè)主鍵的答朋,還不如我們?cè)O(shè)置贷揽,以后在某些搜索條件時(shí)還能用到主鍵的聚簇索引。
6.主鍵推薦用自增id梦碗,而不是uuid禽绪。上面的聚簇索引說(shuō)到每頁(yè)數(shù)據(jù)都是排序的,并且頁(yè)之間也是排序的叉弦,如果是uuid丐一,那么其肯定是隨機(jī)的,其可能從中間插入淹冰,導(dǎo)致頁(yè)的分裂库车,產(chǎn)生很多表碎片。如果是自增的樱拴,那么其有從小到大自增的柠衍,有順序洋满,那么在插入的時(shí)候就添加到當(dāng)前索引的后續(xù)位置。當(dāng)一頁(yè)寫(xiě)滿珍坊,就會(huì)自動(dòng)開(kāi)辟一個(gè)新的頁(yè)牺勾。
七、三范式
第一范式(1NF):是指在關(guān)系模型中阵漏,對(duì)域添加的一個(gè)規(guī)范要求驻民,所有的域都應(yīng)該是原子性的,即數(shù)據(jù)庫(kù)表的每一列都是不可分割的原子數(shù)據(jù)項(xiàng)履怯,而不能是集合回还,數(shù)組,記錄等非原子數(shù)據(jù)項(xiàng)叹洲。即實(shí)體中的某個(gè)屬性有多個(gè)值時(shí)柠硕,必須拆分為不同的屬性。在符合第一范式(1NF)表中的每個(gè)域值只能是實(shí)體的一個(gè)屬性或一個(gè)屬性的一部分运提。簡(jiǎn)而言之蝗柔,第一范式就是無(wú)重復(fù)的域。
第二范式(2NF):在1NF的基礎(chǔ)上民泵,非碼屬性必須完全依賴于候選碼(在1NF基礎(chǔ)上消除非主屬性對(duì)主碼的部分函數(shù)依賴)癣丧,要求實(shí)體的屬性完全依賴于主關(guān)鍵字。所謂完全依賴是指不能存在僅依賴主關(guān)鍵字一部分的屬性栈妆,如果存在坎缭,那么這個(gè)屬性和主關(guān)鍵字的這一部分應(yīng)該分離出來(lái)形成一個(gè)新的實(shí)體,新實(shí)體與原實(shí)體之間是一對(duì)多的關(guān)系签钩。為實(shí)現(xiàn)區(qū)分通常需要為表加上一個(gè)列掏呼,以存儲(chǔ)各個(gè)實(shí)例的唯一標(biāo)識(shí)。簡(jiǎn)而言之铅檩,第二范式就是在第一范式的基礎(chǔ)上屬性完全依賴于主鍵憎夷。
第三范式(3NF):在2NF基礎(chǔ)上,任何非主屬性不依賴于其它非主屬性(在2NF基礎(chǔ)上消除傳遞依賴)昧旨。第三范式(3NF)是第二范式(2NF)的一個(gè)子集拾给,即滿足第三范式(3NF)必須滿足第二范式(2NF)。簡(jiǎn)而言之兔沃,第三范式(3NF)要求一個(gè)關(guān)系中不包含已在其它關(guān)系已包含的非主關(guān)鍵字信息蒋得。
八、SQL優(yōu)化
為查詢緩存優(yōu)化你的查詢乒疏,CURDATE()额衙、 NOW() 、RAND() 無(wú)法生成緩存;
使用EXPLAIN窍侧,
當(dāng)只要一行數(shù)據(jù)時(shí)使用 LIMIT 1
為搜索字段建索引
在Join表的時(shí)候使用相當(dāng)類(lèi)型的例县踢,并將其索引
千萬(wàn)不要 ORDER BY RAND()
避免 SELECT *
永遠(yuǎn)為每張表設(shè)置一個(gè)ID,并且AUTO_INCREMENT
使用 ENUM 而不是 VARCHAR伟件,當(dāng)這些字段的取值是有限而且固定的
盡可能的使用 NOT NULL
Prepared Statements硼啤,抵抗SQL注入攻擊
把IP地址存成 UNSIGNED INT
無(wú)緩沖的查詢 :mysql_unbuffered_query()
固定長(zhǎng)度的表會(huì)更快
垂直分割
用LIMIT拆分大的 DELETE 或 INSERT 語(yǔ)句,防止鎖表時(shí)間過(guò)長(zhǎng)
越小的列會(huì)越快斧账,可用 MEDIUMINT谴返、SMALLINT、TINYINT來(lái)替代 INT 來(lái)做主鍵
使用一個(gè)對(duì)象關(guān)系映射器(Object Relational Mapper)咧织,善用“Lazy Loading”
小心“永久鏈接”