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

注意: 反第三范式: 但是沒有冗余的數(shù)據庫未必是最好的數(shù)據庫,有時為了提高運行效率,就必須降低范式標準,適當保留冗余數(shù)據。具體做法是:在概念數(shù)據模型設計時遵守第三范式,降低范式標準的工作放到物理數(shù)據模型設計時考慮。降低范式就是增加字段,允許冗余。在1對N的情況下,為了提高查詢的效率,是允許部分字段冗余的。
Sql優(yōu)化
Sql的優(yōu)化中,主要是對字段添加索引,主要包含有這四種索引(主鍵索引/唯一索引/全文索引/普通索引)1.主鍵索引添加當一張表,把某個列設為主鍵的時候,則該列就是主鍵索引,下面的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) 技術處理中文
- 使用方法是match(字段名..) against(‘關鍵字’)
- 全文索引一個 叫 停止詞, ?因為在一個文本中,創(chuàng)建索引是一個無窮大的數(shù),因此,對一些常用詞和字符,就不會創(chuàng)建,這些詞,稱為停止詞.
當表的某列被指定為unique約束時,這列就是一個唯一索引
//?創(chuàng)建
create?table?user(id?int?primary?key?auto_increment?,?name?varchar(32)?unique);
這時, name 列就是一個唯一索引,unique字段可以為NULL,并可以有多NULL, 但是如果是具體內容,則不能重復,主鍵字段,不能為NULL,也不能重復。創(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
索引使用的注意事項由于索引本身很大,占用磁盤空間,對dml操作有影響,變慢,滿足以下條件的字段,才應該創(chuàng)建索引。- 肯定在where條經常使用
- 該字段的內容不是唯一的幾個值
- 字段內容不是頻繁變化

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

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

讀寫分離的原理
讀寫分離就是只在主服務器上寫,只在從服務器上讀。基本原理是讓主數(shù)據庫處理事務性查詢,而從服務器處理select查詢。數(shù)據庫復制被用來把事務性查詢導致的變更同步到從數(shù)據庫中。

近期精彩內容推薦:??
?技術總監(jiān):求求你別寫這么多if...else..了

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

