概述
對於mysql的優化是一個綜合性的技術,sql的優化只是其中的一種,其中主要包括 :
- 表的設計合理化(符合3大範式)。
- 添加索引(index) [普通索引、主鍵索引、唯一索引unique、全文索引]。
- 分表技術(水平分割、垂直分割)。
- 讀寫[寫: update/delete/add]分離。
合理設計表(三大範式)
在表的設計中一定條件下要滿足三範式,表的範式,是首先符合第一範式, 才能滿足第二範式 , 進一步滿足第三範式。
第一範式: 即表的列的具有原子性,不可再分解,即列的信息,不能分解, 只有數據庫是關係型數據庫(mysql/oracle/db2/sql server),就自動的滿足第一範式。
第二範式: 表中的記錄是唯一的, 就滿足第二範式, 通常我們設計一個主鍵來實現。
第三範式: 即表中不要有冗餘數據, 就是說,表的信息,如果能夠被推導出來,就不應該單獨的設計一個字段來存放. 比如下面的設計就是不滿足第三範式:
表1存在冗餘表2的數據,正常的設計都會設計成如下:
注意: 反第三範式: 但是沒有冗餘的數據庫未必是最好的數據庫,有時爲了提高運行效率,就必須降低範式標準,適當保留冗餘數據。具體做法是: 在概念數據模型設計時遵守第三範式,降低範式標準的工作放到物理數據模型設計時考慮。降低範式就是增加字段,允許冗餘。
在1對N的情況下,爲了提高查詢的效率,是允許部分字段冗餘的。
Sql優化
Sql的優化中,主要是對字段添加索引,主要包含有這四種索引(主鍵索引/唯一索引/全文索引/普通索引)
主鍵索引添加
當一張表,把某個列設爲主鍵的時候,則該列就是主鍵索引,下面的id 列就是主鍵索引
create table user
(id int unsigned primary key auto_increment ,
name varchar(32) not null defaul ‘’);
如果你創建表時,沒有指定主鍵索引,也可以在創建表後,在添加, 指令:
alter table 表名 add primary key (列名);
//舉例
alter table user add primary key (id);
普通索引
一般來說,普通索引的創建,是先創建表,然後在創建普通索引
比如:
create table user(
id int unsigned,
name varchar(32)
)
create index 索引名 on 表 (列1,列名2);
創建全文索引
全文索引,主要是針對對文件,文本的檢索, 比如文章, 全文索引針對MyISAM有用。創建如下:
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(‘關鍵字’)
- 全文索引一個 叫 停止詞, 因爲在一個文本中,創建索引是一個無窮大的數,因此,對一些常用詞和字符,就不會創建,這些詞,稱爲停止詞.
唯一索引
當表的某列被指定爲unique約束時,這列就是一個唯一索引
// 創建
create table user(id int primary key auto_increment , name varchar(32) unique);
這時, name 列就是一個唯一索引,unique字段可以爲NULL,並可以有多NULL, 但是如果是具體內容,則不能重複,主鍵字段,不能爲NULL,也不能重複。
創建唯一索引
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操作有影響,變慢,滿足以下條件的字段,才應該創建索引。
- 肯定在where條經常使用
- 該字段的內容不是唯一的幾個值
- 字段內容不是頻繁變化
explain 可以幫助我們在不真正執行某個sql語句時,就執行mysql怎樣執行,這樣利用我們去分析sql指令。
- id:查詢的序列號。
- select_type:查詢類型。
- table:查詢表名。
- type:掃描方式,all表示全表掃描。
- possible_keys:可是使用到的索引。
- key:實際使用到的索引。
- rows:該sql掃面了多少行。
- Extra:sql語句額外的信息,比如排序方式
sql語句的小技巧
- 在使用group by 分組查詢是,默認分組後,還會排序,可能會降低速度,在group by 後面增加 order by null 就可以防止排序。如下圖所示
- 有些情況下,可以使用連接來替代子查詢。因爲使用join,MySQL不需要在內存中創建臨時表。
select * from dept, emp where dept.deptno=emp.deptno;
// 替換成
select * from dept left join emp on dept.deptno=emp.deptno;
正確的選擇mysql的存儲引擎
Myisam : 如果表對事務要求不高,同時是以查詢和添加爲主的,我們考慮使用myisam存儲引擎. ,比如 bbs 中的 發帖表,回覆表。
INNODB : 對事務要求高,保存的數據都是重要數據,我們建議使用INNODB,比如訂單表,賬號表。
如果你的數據庫的存儲引擎是myisam,請一定記住要定時進行碎片整理
分表技術
爲什麼要分表?
(1) 如果一個表的每條記錄的內容很大,那麼就需要更多的IO操作,如果字段值比較大,而使用頻率相對比較低,可以將大字段移到另一張表中,當查詢不查大字段的時候,這樣就減少了I/O操作
(2)如果表的數據量非常非常大,那麼查詢就變的比較慢;也就是表的數據量影響這查詢的性能。
(3)表中的數據本來就有獨立性,例如分別記錄各個地區的數據或者不同時期的數據,特別是有些數據常用,而另外一些數據不常用。
(4) 分表技術有(水平分割和垂直分割)
垂直分割
垂直分割是指數據表列的拆分,把一張列比較多的表拆分爲多張表。 垂直分割一般用於拆分大字段和訪問頻率低的字段,分離冷熱數據。
垂直分割比較常見:例如博客系統中的文章表,比如文章tbl_articles
(id, titile, summary, content, user_id, create_time),因爲文章中的內容content會比較長,放在tbl_articles中會嚴重影響表的查詢速度,所以將內容放到tbl_articles_detail(article_id, content),像文章列表只需要查詢tbl_articles中的字段即可。
垂直拆分的優點: 可以使得行數據變小,在查詢時減少讀取的Block數,減少I/O次數。此外,垂直分區可以簡化表的結構,易於維護。
垂直拆分的缺點: 主鍵會出現冗餘,需要管理冗餘列,並會引起Join操作,可以通過在應用層進行Join來解決。此外,垂直分區會讓事務變得更加複雜。
水平分割
水平拆分是指數據錶行數據的拆分,表的行數超過500萬行或者單表容量超過10GB時,查詢就會變慢,這時可以把一張的表的數據拆成多張表來存放。水平分表儘可能使每張表的數據量相當,比較均勻。
水平拆分會給應用增加複雜度,它通常在查詢是需要多個表名,查詢所有數據需要union操作。在許多數據庫應用中,這種複雜性會超過它帶來的優點。
因爲只要索引關鍵字不大,則在索引用於查詢時,表中增加2-3倍數據量,查詢時也就增加讀一個索引層的磁盤次數,所以水平拆分要考慮數據量的增長速度,根據實際情況決定是否需要對錶進行水平拆分。
水平分割最重要的是找到分割的標準,不同的表應根據業務找出不同的標準
- 用戶表可以根據用戶的手機號段進行分割如user183、user150、user153、user189等,每個號段就是一張表
- 用戶表也可以根據用戶的id進行分割,加入分3張表user0,user1,user2,如果用戶的id%3=0就查詢user0表,
如果用戶的id%3=1就查詢user1表 - 對於訂單表可以按照訂單的時間進行分表
讀寫分離
實現MySQL讀寫分離的前提是我們已經將MySQL主從複製配置完畢,讀寫分離實現方式:
(1)配置多數據源。
(2)使用mysql的proxy中間件代理工具。
主從複製的原理
MySQL的主從複製和讀寫分離兩者有着緊密的聯繫,首先要部署主從複製,只有主從複製完成了才能在此基礎上進行數據的讀寫分離。
讀寫分離的原理
讀寫分離就是隻在主服務器上寫,只在從服務器上讀。基本原理是讓主數據庫處理事務性查詢,而從服務器處理select查詢。數據庫複製被用來把事務性查詢導致的變更同步到從數據庫中。