转-《高性能mysql》并不是一本好书——SQL笔记
轉(zhuǎn)自:?https://book.douban.com/review/8122660/
?
版權(quán)歸作者所有,任何形式轉(zhuǎn)載請(qǐng)聯(lián)系作者。
作者:姚澤源(來(lái)自豆瓣)
來(lái)源:https://book.douban.com/review/8122660/
在知乎上發(fā)過(guò)一次,這里也發(fā)一遍吧
--------正文開始--------
草草翻完了《高性能MySQL》,印象最深的地方就是:這確實(shí)不適合初學(xué)者去看。
花了三個(gè)月的時(shí)間慢慢看完了這本,看的一頭霧水。第一章概論講了不少新奇的概念,比如隔離級(jí)別,比如多版本并發(fā)控制(MVVC)。但是從第二章起,所講的內(nèi)容基本就和日常應(yīng)用沒什么太大關(guān)系了。如果要簡(jiǎn)單概括一下的話就是
1. 儲(chǔ)存引擎務(wù)必使用InnoDB
2. 創(chuàng)建新數(shù)據(jù)庫(kù)時(shí)要用最新的MySQL版本(當(dāng)然是GA版)
3. 輕易不要升級(jí)MySQL
然后就沒了。對(duì)于其他的內(nèi)容,不管是服務(wù)器性能優(yōu)化還是MySQL主從備份,這些其實(shí)都和一名普通的技術(shù)人員沒有關(guān)系。相較于書中提到的通過(guò)修改frm文件實(shí)現(xiàn)快速新增列這種神奇方法,技術(shù)人員最好的做法還是:盡可能的避免使用alter語(yǔ)句或者說(shuō)在項(xiàng)目一開始時(shí)就要想好數(shù)據(jù)表的用途。如果你是想改進(jìn)自己的SQL水平的話,那應(yīng)該去看 SQL快速優(yōu)化300例 ,至少,不是這本書。
寫一下收獲吧(SQL相關(guān),不僅僅是MySQL),畢竟翻完了不是。
1. 盡量避免在線上使用alter
在使用alter新增列時(shí),會(huì)引發(fā)一個(gè)全表鎖,數(shù)據(jù)庫(kù)會(huì)暫停響應(yīng)直到新列添加完成(在已有數(shù)據(jù)中添加新列,在數(shù)據(jù)庫(kù)表結(jié)構(gòu)中添加列定義)。鎖定的時(shí)間隨表內(nèi)數(shù)據(jù)量的大小線性增長(zhǎng)。如果是在線上環(huán)境的話,即使很短的時(shí)間,也夠阻塞不少請(qǐng)求了←_←
2. 可以通過(guò)冗余數(shù)據(jù)來(lái)提升SQL查詢的性能
在標(biāo)準(zhǔn)的數(shù)據(jù)庫(kù)教科書中,數(shù)據(jù)表結(jié)構(gòu)按說(shuō)是要符合范式要求的(1NF~5NF)。比如,通過(guò)把用戶信息和訂單內(nèi)容獨(dú)立開,這樣就可以設(shè)計(jì)出來(lái)沒有冗余數(shù)據(jù)的數(shù)據(jù)庫(kù)表結(jié)構(gòu)——俗稱學(xué)院派數(shù)據(jù)庫(kù)表結(jié)構(gòu)。但是,學(xué)院派依托的環(huán)境是銀行系統(tǒng)這樣的大型工程,查詢帶來(lái)的性能損耗遠(yuǎn)小于冗余數(shù)據(jù)帶來(lái)的損耗。但在真實(shí)應(yīng)用中,表里的數(shù)據(jù)很少能達(dá)到1000萬(wàn)行以上的,在這時(shí),大部分的性能全浪費(fèi)在多次查詢上了。這時(shí)候,學(xué)院派的做法就不如直接在數(shù)據(jù)表中添加冗余數(shù)據(jù)(例如把用戶手機(jī)號(hào)和訂單一起存取),這樣在展示的時(shí)候一條SQL就可以搞定。
> 『PHP絕大部分的性能都浪費(fèi)在和MySQL服務(wù)器通訊上了』
3. 使用tinyint或者varchar作為枚舉類型,而不是使用enum
理由很簡(jiǎn)單: enum在新增類型的時(shí)候需要使用alter語(yǔ)句進(jìn)行全表新增,線上數(shù)據(jù)庫(kù)時(shí)不時(shí)的來(lái)上一回全表鎖誰(shuí)受的了。。。
一般來(lái)說(shuō),使用 tinyint + 代碼中利用常量進(jìn)行定義 是最好的方案,如果要增強(qiáng)可讀性的話可以使用varchar, 因?yàn)槌A恳还惨膊怀^(guò)10個(gè)字母,從性能上來(lái)說(shuō)varchar也可以接受
4. 可視化工具
客戶端的話個(gè)人建議使用adminer,有ngnix之后配上一個(gè)index.php文件就能用。非要使用客戶端的話用MySQL Workbench也可以,MySQL自己出的。這兩個(gè)都在《高性能MySQL》的推薦之列,可以考慮
5. 使用調(diào)試語(yǔ)句查看性能
常用的調(diào)試語(yǔ)句如EXPLAIN, SHOW這種,現(xiàn)用現(xiàn)查即可
6. 索引數(shù)據(jù)一般都在內(nèi)存里
結(jié)論:排序時(shí)直接使用索引排序是最快的,索引不要太多,太多之后跟把整個(gè)表放內(nèi)存里就等效了(還不如使用Redis)
補(bǔ)充:排序時(shí)EXPLAIN發(fā)現(xiàn)不是index,而是filesort也不用太擔(dān)心,因?yàn)橹挥羞@兩種狀態(tài),不是index就是filesort,性能只要不是太坑直接上就行
7. 分表分庫(kù),歷史數(shù)據(jù)獨(dú)立建表
MySQL處理1000萬(wàn)行以下的數(shù)據(jù)時(shí)性能是非常好的——那1000萬(wàn)行以上時(shí)怎么辦呢?
直接分表啊。
比如,可以按時(shí)間分,自增id在500萬(wàn)之前的,獨(dú)立分到一個(gè)表里,在程序代碼里寫死,用到的時(shí)候再去讀
或者,按一個(gè)數(shù)取模,根據(jù)余數(shù)選擇對(duì)應(yīng)的表。
8. 對(duì)于重要數(shù)據(jù),一定要開啟二進(jìn)制日志
手滑刪過(guò)全表的同學(xué)都懂。。。
然后,解釋下兩個(gè)概念:
1. 隔離級(jí)別
每執(zhí)行一次SQL稱為一件事務(wù),如果事務(wù)所涉及到的內(nèi)容在事務(wù)進(jìn)行中發(fā)生了改變,對(duì)應(yīng)于事務(wù)所能讀取到的實(shí)際內(nèi)容,就產(chǎn)生了四種標(biāo)準(zhǔn)情況,這四種標(biāo)準(zhǔn)情況被稱為四種隔離級(jí)別(僅就MySQL而言,對(duì)于其他數(shù)據(jù)庫(kù)實(shí)現(xiàn)可能會(huì)有不同的區(qū)分標(biāo)準(zhǔn))
1. READ UNCOMMIT(未提交讀)
在READ UNCOMMIT級(jí)別中,即使沒有提交,每個(gè)事務(wù)的操作對(duì)于其他事務(wù)也都是可見的。在這種情況下,事務(wù)可以讀取未提交的數(shù)據(jù),又稱臟讀(DIRTY READ)。從性能上來(lái)說(shuō),臟讀并不比其他模式優(yōu)秀多少,但是會(huì)引發(fā)各種嚴(yán)重的問(wèn)題(比如說(shuō)銀行存款數(shù)據(jù)寫入到一半來(lái)了一個(gè)讀操作。。。)。一般情況下,不建議使用
2. READ COMMIT(未提交讀)
大部分?jǐn)?shù)據(jù)庫(kù)系統(tǒng)默認(rèn)的隔離級(jí)別都是READ COMMIT(但MySQL不是)。在READ COMMIT這一級(jí)別中,事務(wù)所修改的數(shù)據(jù)只有提交了之后才會(huì)被其他事務(wù)讀取到。換句話說(shuō),一個(gè)事物從開始之后到結(jié)束之前,所做的任何修改對(duì)其他事物都是不可見的。這個(gè)級(jí)別實(shí)際上已經(jīng)比較符合我們讀取數(shù)據(jù)的預(yù)期了。但是,如果執(zhí)行兩次同樣的查詢,可能會(huì)出現(xiàn)兩遍結(jié)果不一致的情況(查詢執(zhí)行過(guò)程中有其他事務(wù)提交完成),所以,這一級(jí)別又叫不可重復(fù)讀(nonrepeatable read)
3. REPEATABLE READ(可重復(fù)讀)
REPEATABLE READ解決了臟讀的問(wèn)題,同時(shí)也是MySQL的默認(rèn)事務(wù)隔離級(jí)別。這一級(jí)別保證了在同一個(gè)事務(wù)中多次讀取同樣的記錄結(jié)果是一致的。但是理論上,可重復(fù)讀還是沒法解決幻讀(Phantom Read)的問(wèn)題。幻讀是指:在某個(gè)事務(wù)讀取某個(gè)范圍內(nèi)的的記錄時(shí)(id>1 && id < 100),另外一個(gè)事物又再該范圍內(nèi)插入了新紀(jì)錄,當(dāng)之前的事務(wù)再次讀取該范圍的記錄時(shí),就會(huì)產(chǎn)生幻行(Phantom Row)。不過(guò)InnoDB通過(guò)多版本并發(fā)控制(MVVC, Multiversion Concurrency Control)解決了這個(gè)問(wèn)題
4. SERIALIZABLE(可串行話)
SERIALIZABLE是最高的隔離級(jí)別。它通過(guò)強(qiáng)制讓事務(wù)串行執(zhí)行,可以避免前面所說(shuō)的全部問(wèn)題。本質(zhì)上說(shuō),SERIALIZABLE會(huì)在讀取的每一行數(shù)據(jù)上都加上鎖, 對(duì)性能影響非常嚴(yán)重。只有在非常需要確保數(shù)據(jù)一致性,且可以接受沒有并發(fā)的情況下,才可以考慮使用此級(jí)別
2. 多版本并發(fā)控制
這是個(gè)很玄乎的詞,但說(shuō)白了就是:通過(guò)保存數(shù)據(jù)在某個(gè)時(shí)間點(diǎn)的快照,來(lái)確保對(duì)于不同開始時(shí)間的事務(wù),他們對(duì)于同一張表,在同一時(shí)刻看到的數(shù)據(jù)都是一樣的。
對(duì)于InnoDB來(lái)說(shuō)就是:通過(guò)在每行記錄后邊保存兩個(gè)隱藏列,一列記錄創(chuàng)建時(shí)間,一列記錄過(guò)期時(shí)間(實(shí)際上存儲(chǔ)的是系統(tǒng)版本號(hào)),每開始一個(gè)事務(wù),系統(tǒng)版本號(hào)都會(huì)自動(dòng)遞增。在事務(wù)開始時(shí)刻的系統(tǒng)版本號(hào)就會(huì)作為事務(wù)的版本號(hào),用來(lái)作為數(shù)據(jù)庫(kù)查詢的依據(jù),以此實(shí)現(xiàn):多版本并發(fā)控制
大致就這些。看起來(lái)很高大上的一本書,實(shí)際上看了跟沒看差不多(DBA除外)。不推薦閱讀/購(gòu)買
?
(但我對(duì)高性能mysql的印象蠻好的,推薦閱讀。)
?
總結(jié)
以上是生活随笔為你收集整理的转-《高性能mysql》并不是一本好书——SQL笔记的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 怎么查别人手机号
- 下一篇: 学习PL/SQL最好的书籍推荐