你要的Mysql優化提高筆記整理,來自於一位大佬的筆記

概述

對於mysql的優化是一個綜合性的技術,sql的優化只是其中的一種,其中主要包括 :

  1. 表的設計合理化(符合3大範式)。
  2. 添加索引(index) [普通索引、主鍵索引、唯一索引unique、全文索引]。
  3. 分表技術(水平分割、垂直分割)。
  4. 讀寫[寫: 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(‘非科班’); 

說明:

  1. 在mysql中fulltext 索引只針對 myisam生效
  2. mysql自己提供的fulltext針對英文生效->sphinx (coreseek) 技術處理中文
  3. 使用方法是match(字段名…) against(‘關鍵字’)
  4. 全文索引一個 叫 停止詞, 因爲在一個文本中,創建索引是一個無窮大的數,因此,對一些常用詞和字符,就不會創建,這些詞,稱爲停止詞.

唯一索引

當表的某列被指定爲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操作有影響,變慢,滿足以下條件的字段,才應該創建索引。

  1. 肯定在where條經常使用
  2. 該字段的內容不是唯一的幾個值
  3. 字段內容不是頻繁變化

explain 可以幫助我們在不真正執行某個sql語句時,就執行mysql怎樣執行,這樣利用我們去分析sql指令。

  1. id:查詢的序列號。
  2. select_type:查詢類型。
  3. table:查詢表名。
  4. type:掃描方式,all表示全表掃描。
  5. possible_keys:可是使用到的索引。
  6. key:實際使用到的索引。
  7. rows:該sql掃面了多少行。
  8. Extra:sql語句額外的信息,比如排序方式

sql語句的小技巧

  1. 在使用group by 分組查詢是,默認分組後,還會排序,可能會降低速度,在group by 後面增加 order by null 就可以防止排序。如下圖所示

  1. 有些情況下,可以使用連接來替代子查詢。因爲使用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倍數據量,查詢時也就增加讀一個索引層的磁盤次數,所以水平拆分要考慮數據量的增長速度,根據實際情況決定是否需要對錶進行水平拆分。

水平分割最重要的是找到分割的標準,不同的表應根據業務找出不同的標準

  1. 用戶表可以根據用戶的手機號段進行分割如user183、user150、user153、user189等,每個號段就是一張表
  2. 用戶表也可以根據用戶的id進行分割,加入分3張表user0,user1,user2,如果用戶的id%3=0就查詢user0表,
    如果用戶的id%3=1就查詢user1表
  3. 對於訂單表可以按照訂單的時間進行分表

讀寫分離

實現MySQL讀寫分離的前提是我們已經將MySQL主從複製配置完畢,讀寫分離實現方式:
(1)配置多數據源。
(2)使用mysql的proxy中間件代理工具。

主從複製的原理

MySQL的主從複製和讀寫分離兩者有着緊密的聯繫,首先要部署主從複製,只有主從複製完成了才能在此基礎上進行數據的讀寫分離。

讀寫分離的原理

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章