Mysql優(yōu)化提高筆記整理,來自于一位鵝廠大佬的筆記
作者丨黎杜來源丨非科班的科班?
概述
對于mysql的優(yōu)化是一個綜合性的技術(shù),sql的優(yōu)化只是其中的一種,其中主要包括?- 表的設(shè)計合理化(符合3大范式)。
- 添加索引(index) [普通索引、主鍵索引、唯一索引unique、全文索引]。
- 分表技術(shù)(水平分割、垂直分割)。
- 讀寫[寫: update/delete/add]分離。
合理設(shè)計表
在表的設(shè)計中一定條件下要滿足三范式,表的范式,是首先符合第一范式, 才能滿足第二范式 , 進(jìn)一步滿足第三范式。第一范式: 即表的列的具有原子性,不可再分解,即列的信息,不能分解, 只有數(shù)據(jù)庫是關(guān)系型數(shù)據(jù)庫(mysql/oracle/db2/sql server),就自動的滿足第一范式。第二范式: 表中的記錄是唯一的, 就滿足第二范式, 通常我們設(shè)計一個主鍵來實(shí)現(xiàn)。第三范式: 即表中不要有冗余數(shù)據(jù), 就是說,表的信息,如果能夠被推導(dǎo)出來,就不應(yīng)該單獨(dú)的設(shè)計一個字段來存放. 比如下面的設(shè)計就是不滿足第三范式:
表1存在冗余表2的數(shù)據(jù),正常的設(shè)計都會設(shè)計成如下:

注意: 反第三范式: 但是沒有冗余的數(shù)據(jù)庫未必是最好的數(shù)據(jù)庫,有時為了提高運(yùn)行效率,就必須降低范式標(biāo)準(zhǔn),適當(dāng)保留冗余數(shù)據(jù)。具體做法是:在概念數(shù)據(jù)模型設(shè)計時遵守第三范式,降低范式標(biāo)準(zhǔn)的工作放到物理數(shù)據(jù)模型設(shè)計時考慮。降低范式就是增加字段,允許冗余。在1對N的情況下,為了提高查詢的效率,是允許部分字段冗余的。
Sql優(yōu)化
Sql的優(yōu)化中,主要是對字段添加索引,主要包含有這四種索引(主鍵索引/唯一索引/全文索引/普通索引)1.主鍵索引添加當(dāng)一張表,把某個列設(shè)為主鍵的時候,則該列就是主鍵索引,下面的id 列就是主鍵索引create?table?user
(id?int?unsigned?primary?key?auto_increment?,
name?varchar(32)?not?null?defaul?‘’);
如果你創(chuàng)建表時,沒有指定主鍵索引,也可以在創(chuàng)建表后,在添加, 指令:alter?table?表名?add?primary?key?(列名);
//舉例
alter?table?user?add?primary?key?(id);
2.普通索引一般來說,普通索引的創(chuàng)建,是先創(chuàng)建表,然后在創(chuàng)建普通索引比如:
create?table?user(
id?int?unsigned,
name?varchar(32)
)
create?index?索引名?on?表?(列1,列名2);
3.創(chuàng)建全文索引全文索引,主要是針對對文件,文本的檢索, 比如文章, 全文索引針對MyISAM有用。創(chuàng)建如下:CREATE?TABLE?articles?(
???????id?INT?UNSIGNED?AUTO_INCREMENT?NOT?NULL?PRIMARY?KEY,
???????title?VARCHAR(200),
???????body?TEXT,
???????FULLTEXT?(title,body)
?????)engine=myisam?charset?utf8;
如何使用全文索引:select?*?from?articles?where?body?like?‘%非科班%’;??//不會使用到全文索引
//?查看是否使用索引:
explain??select?*?from?articles?where?body?like?‘%非科班%’
//?正確的用法是:
select?*?from?articles?where?match(title,body)?against(‘非科班’);?
說明:- 在mysql中fulltext 索引只針對 myisam生效
- mysql自己提供的fulltext針對英文生效->sphinx (coreseek) 技術(shù)處理中文
- 使用方法是match(字段名..) against(‘關(guān)鍵字’)
- 全文索引一個 叫 停止詞, ?因?yàn)樵谝粋€文本中,創(chuàng)建索引是一個無窮大的數(shù),因此,對一些常用詞和字符,就不會創(chuàng)建,這些詞,稱為停止詞.
當(dāng)表的某列被指定為unique約束時,這列就是一個唯一索引
//?創(chuàng)建
create?table?user(id?int?primary?key?auto_increment?,?name?varchar(32)?unique);
這時, name 列就是一個唯一索引,unique字段可以為NULL,并可以有多NULL, 但是如果是具體內(nèi)容,則不能重復(fù),主鍵字段,不能為NULL,也不能重復(fù)。創(chuàng)建唯一索引create?table?user(id?int?primary?key?auto_increment,?name?varchar(32));
create?unique?index?索引名??on?表名?(列表..);
查詢索引desc?表名??//不能夠顯示索引名
show?index(es)?from?表名
show?keys?from?表名
刪除索引alter?table?表名?drop?index?索引名;?
//如果刪除主鍵索引。
alter?table?表名?drop?primary?key
索引使用的注意事項(xiàng)由于索引本身很大,占用磁盤空間,對dml操作有影響,變慢,滿足以下條件的字段,才應(yīng)該創(chuàng)建索引。- 肯定在where條經(jīng)常使用
- 該字段的內(nèi)容不是唯一的幾個值
- 字段內(nèi)容不是頻繁變化

- id:查詢的序列號。
- select_type:查詢類型。
- table:查詢表名。
- type:掃描方式,all表示全表掃描。
- possible_keys:可是使用到的索引。
- key:實(shí)際使用到的索引。
- rows:該sql掃面了多少行。
- Extra:sql語句額外的信息,比如排序方式
- 在使用group by 分組查詢時,默認(rèn)分組后,還會排序,可能會降低速度,在group by 后面增加 order by null 就可以防止排序。如下圖所示

- 有些情況下,可以使用連接來替代子查詢。因?yàn)槭褂胘oin,MySQL不需要在內(nèi)存中創(chuàng)建臨時表。
select?*?from?dept,?emp?where?dept.deptno=emp.deptno;?
//?替換成
select?*?from?dept?left?join?emp?on?dept.deptno=emp.deptno;??
正確的選擇mysql的存儲引擎
Myisam : 如果表對事務(wù)要求不高,同時是以查詢和添加為主的,我們考慮使用myisam存儲引擎. ,比如 bbs 中的 發(fā)帖表,回復(fù)表。INNODB : 對事務(wù)要求高,保存的數(shù)據(jù)都是重要數(shù)據(jù),我們建議使用INNODB,比如訂單表,賬號表。
如果你的數(shù)據(jù)庫的存儲引擎是myisam,請一定記住要定時進(jìn)行碎片整理
分表技術(shù)
為什么要分表?垂直分割垂直分割是指數(shù)據(jù)表列的拆分,把一張列比較多的表拆分為多張表。垂直分割一般用于拆分大字段和訪問頻率低的字段,分離冷熱數(shù)據(jù)。垂直分割比較常見:例如博客系統(tǒng)中的文章表,比如文章tbl_articles
(1) 如果一個表的每條記錄的內(nèi)容很大,那么就需要更多的IO操作,如果字段值比較大,而使用頻率相對比較低,可以將大字段移到另一張表中,當(dāng)查詢不查大字段的時候,這樣就減少了I/O操作
(2)如果表的數(shù)據(jù)量非常非常大,那么查詢就變的比較慢;也就是表的數(shù)據(jù)量影響這查詢的性能。
(3)表中的數(shù)據(jù)本來就有獨(dú)立性,例如分別記錄各個地區(qū)的數(shù)據(jù)或者不同時期的數(shù)據(jù),特別是有些數(shù)據(jù)常用,而另外一些數(shù)據(jù)不常用。
?(4) ?分表技術(shù)有(水平分割和垂直分割)
(id, titile, summary, content, user_id, create_time),因?yàn)槲恼轮械膬?nèi)容content會比較長,放在tbl_articles中會嚴(yán)重影響表的查詢速度,所以將內(nèi)容放到tbl_articles_detail(article_id, content),像文章列表只需要查詢tbl_articles中的字段即可。垂直拆分的優(yōu)點(diǎn):可以使得行數(shù)據(jù)變小,在查詢時減少讀取的Block數(shù),減少I/O次數(shù)。此外,垂直分區(qū)可以簡化表的結(jié)構(gòu),易于維護(hù)。垂直拆分的缺點(diǎn):主鍵會出現(xiàn)冗余,需要管理冗余列,并會引起Join操作,可以通過在應(yīng)用層進(jìn)行Join來解決。此外,垂直分區(qū)會讓事務(wù)變得更加復(fù)雜。水平分割水平拆分是指數(shù)據(jù)表行數(shù)據(jù)的拆分,表的行數(shù)超過500萬行或者單表容量超過10GB時,查詢就會變慢,這時可以把一張的表的數(shù)據(jù)拆成多張表來存放。水平分表盡可能使每張表的數(shù)據(jù)量相當(dāng),比較均勻。水平拆分會給應(yīng)用增加復(fù)雜度,它通常在查詢是需要多個表名,查詢所有數(shù)據(jù)需要union操作。在許多數(shù)據(jù)庫應(yīng)用中,這種復(fù)雜性會超過它帶來的優(yōu)點(diǎn)。因?yàn)橹灰饕P(guān)鍵字不大,則在索引用于查詢時,表中增加2-3倍數(shù)據(jù)量,查詢時也就增加讀一個索引層的磁盤次數(shù),所以水平拆分要考慮數(shù)據(jù)量的增長速度,根據(jù)實(shí)際情況決定是否需要對表進(jìn)行水平拆分。水平分割最重要的是找到分割的標(biāo)準(zhǔn),不同的表應(yīng)根據(jù)業(yè)務(wù)找出不同的標(biāo)準(zhǔn)
- 用戶表可以根據(jù)用戶的手機(jī)號段進(jìn)行分割如user183、user150、user153、user189等,每個號段就是一張表
- 用戶表也可以根據(jù)用戶的id進(jìn)行分割,加入分3張表user0,user1,user2,如果用戶的id%3=0就查詢user0表,
如果用戶的id%3=1就查詢user1表 - 對于訂單表可以按照訂單的時間進(jìn)行分表
讀寫分離
實(shí)現(xiàn)MySQL讀寫分離的前提是我們已經(jīng)將MySQL主從復(fù)制配置完畢,讀寫分離實(shí)現(xiàn)方式:(1)配置多數(shù)據(jù)源。
(2)使用mysql的proxy中間件代理工具。主從復(fù)制的原理
MySQL的主從復(fù)制和讀寫分離兩者有著緊密的聯(lián)系,首先要部署主從復(fù)制,只有主從復(fù)制完成了才能在此基礎(chǔ)上進(jìn)行數(shù)據(jù)的讀寫分離。

讀寫分離的原理
讀寫分離就是只在主服務(wù)器上寫,只在從服務(wù)器上讀?;驹硎亲屩鲾?shù)據(jù)庫處理事務(wù)性查詢,而從服務(wù)器處理select查詢。數(shù)據(jù)庫復(fù)制被用來把事務(wù)性查詢導(dǎo)致的變更同步到從數(shù)據(jù)庫中。

近期精彩內(nèi)容推薦:??
?復(fù)工期來臨,騰訊員工曬的照片引網(wǎng)友關(guān)注
?技術(shù)總監(jiān):求求你別寫這么多if...else..了

在看點(diǎn)這里
好文分享給更多人↓↓
評論
圖片
表情
