1. 程式人生 > 實用技巧 >MySQL優化-常用方法

MySQL優化-常用方法

小型專案可能對資料庫要求沒有那麼大,但是對於百萬千萬級以上資料,查詢等資料庫便會有顯著下降,以下是個人專案中用到的方法(持續補充中...):

1.建立資料庫

(1)使用合適的資料型別。能用char就不用varchar,能用mediumint就不用bigint。減少不必要的空間開銷。

(2)合理使用外來鍵。

2.查詢資料庫

(1)使用join代替子查詢。

(2)使用union代替臨時表建立。

(3)查詢需要的欄位。

(4)減少比較操作,像like之類的。

3.索引[主鍵索引|唯一索引|普通索引|全文索引|空間索引]

合理建立索引

4.分割槽分表(瓶頸為單庫容量)

  • 概念

分割槽(圖書的章節) 就是把一張表的資料分成N個區塊,在邏輯上看最終只是一張表,但底層是由N個物理區塊組成的

分表(圖書館的圖書) 就是把一張表按一定的規則分解成N個具有獨立儲存空間的實體表。系統讀寫時需要根據定義好的規則得到對應的字表明,然後操作它。

分庫(圖書館,未使用過不做詳細介紹) 一旦分表,一個庫中的表會越來越多。

  • 使用場景

(1)分割槽

  • 一張表的查詢速度已經慢到影響使用的時候。

  • sql經過優化

  • 資料量大

  • 表中的資料是分段的
  • 對資料的操作往往只涉及一部分資料,而不是所有的資料

(2)分表

  • 一張表的查詢速度已經慢到影響使用的時候。

  • sql經過優化

  • 資料量大
  • 當頻繁插入或者聯合查詢時,速度變慢

  • 操作

(1)分割槽

新建表:

//range分割槽方式
drop
table if exists staff; create table staff( id int not null, fname varchar(30), lname varchar(30), hired date not null default '1970-01-01', separated date not null default '9999-12-31', job_code int not null default 0, store_id int not null default 0 )engine=myisam default charset=utf8 partition
by range(year(separated))( partition p0 values less than (1991), partition p1 values less than (1996), partition p2 values less than (2001), partition p4 values less than MAXVALUE );

//hash分割槽方式
drop table if exists staff;
create table staff(
  id int not null,
  fname varchar(30),
  lname varchar(30),
  hired date not null default '1970-01-01',
  separated date not null default '9999-12-31',
  job_code int not null default 0,
  store_id int not null default 0
)
partition by hash(store_id)
partitions 4;
less than MAXVALUE一定要注意新增,要不然超出範圍將報錯。

刪除表:
alter table staff drop partition p0;

查詢表:

select count(*) from staff where year(separated) = 200 group by store_id;
//自動查詢p2分割槽

5.資料庫引擎

6.讀寫分離(配置)

適用場景:讀操作遠遠多於寫操作

目標:有效減輕Master庫的壓力,又可以把使用者查詢資料的請求分發到不同的Slave庫,從而保證系統的健壯性。

實現方式1:應用內部路由

不推薦!需要應用內切換資料來源且實現高可用。個人也沒有用過。

實現方式2:代理

個人用的是mysql-proxy代理中介軟體,可配置

缺點:增加了一層,網路消耗伴隨增加

7.預處理

使用Redis/ElasticSearch

這是第三方元件完成的快取機制


如何定位查詢慢的語句:

利用資料庫慢查詢功能,設定步驟如下

(1)臨時開啟慢查詢(永久開啟得改/etc/my.cfg)

set gloabal slow_query_log=on(對應的關閉為off)

(2)設定時間長度,超過的語句將被記錄

set long_query_time=5(單位秒)

(3)儲存方式設為file

set log_output=file(預設為null,還支援table,資料將放在slow_log表中)

(4)檢視儲存位置

show variables like '%query%'

檔案位置為slow_query_log_file

(5)拿到第4步的sql語句,執行explain+SQL語句

作用:

  • 表的讀取順序
  • 資料讀取操作的操作型別
  • 哪些索引可以使用
  • 哪些索引被實際使用
  • 表之間的引用
  • 每張表有多少行被優化器查詢

分析得到的資料:

資訊 描述
id 查詢的序號,包含一組數字,表示查詢中執行select子句或操作表的順序
**兩種情況**
id相同,執行順序從上往下
id不同,id值越大,優先順序越高,越先執行
select_type 查詢型別,主要用於區別普通查詢,聯合查詢,子查詢等的複雜查詢
1、simple ——簡單的select查詢,查詢中不包含子查詢或者UNION
2、primary ——查詢中若包含任何複雜的子部分,最外層查詢被標記
3、subquery——在select或where列表中包含了子查詢
4、derived——在from列表中包含的子查詢被標記為derived(衍生),MySQL會遞迴執行這些子查詢,把結果放到臨時表中
5、union——如果第二個select出現在UNION之後,則被標記為UNION,如果union包含在from子句的子查詢中,外層select被標記為derived
6、union result:UNION 的結果
table 輸出的行所引用的表
type 顯示聯結型別,顯示查詢使用了何種型別,按照從最佳到最壞型別排序
1、system:表中僅有一行(=系統表)這是const聯結型別的一個特例。
2、const:表示通過索引一次就找到,const用於比較primary key或者unique索引。因為只匹配一行資料,所以如果將主鍵置於where列表中,mysql能將該查詢轉換為一個常量
3、eq_ref:唯一性索引掃描,對於每個索引鍵,表中只有一條記錄與之匹配。常見於唯一索引或者主鍵掃描
4、ref:非唯一性索引掃描,返回匹配某個單獨值的所有行,本質上也是一種索引訪問,它返回所有匹配某個單獨值的行,可能會找多個符合條件的行,屬於查詢和掃描的混合體
5、range:只檢索給定範圍的行,使用一個索引來選擇行。key列顯示使用了哪個索引,一般就是where語句中出現了between,in等範圍的查詢。這種範圍掃描索引掃描比全表掃描要好,因為它開始於索引的某一個點,而結束另一個點,不用全表掃描
6、index:index 與all區別為index型別只遍歷索引樹。通常比all快,因為索引檔案比資料檔案小很多。
7、all:遍歷全表以找到匹配的行
注意:一般保證查詢至少達到range級別,最好能達到ref。
possible_keys 指出MySQL能使用哪個索引在該表中找到行
key 顯示MySQL實際決定使用的鍵(索引)。如果沒有選擇索引,鍵是NULL。查詢中如果使用覆蓋索引,則該索引和查詢的select欄位重疊。
key_len 表示索引中使用的位元組數,該列計算查詢中使用的索引的長度在不損失精度的情況下,長度越短越好。如果鍵是NULL,則長度為NULL。該欄位顯示為索引欄位的最大可能長度,並非實際使用長度。
ref 顯示索引的哪一列被使用了,如果有可能是一個常數,哪些列或常量被用於查詢索引列上的值
rows 根據表統計資訊以及索引選用情況,大致估算出找到所需的記錄所需要讀取的行數
Extra 包含不適合在其他列中顯示,但是十分重要的額外資訊
1、Using filesort:說明mysql會對資料適用一個外部的索引排序。而不是按照表內的索引順序進行讀取。MySQL中無法利用索引完成排序操作稱為“檔案排序”
2、Using temporary:使用了臨時表儲存中間結果,mysql在查詢結果排序時使用臨時表。常見於排序order by和分組查詢group by。
3、Using index:表示相應的select操作用使用覆蓋索引,避免訪問了表的資料行。如果同時出現using where,表名索引被用來執行索引鍵值的查詢;如果沒有同時出現using where,表名索引用來讀取資料而非執行查詢動作。
4、Using where :表明使用where過濾
5、using join buffer:使用了連線快取
6、impossible where:where子句的值總是false,不能用來獲取任何元組
7、select tables optimized away:在沒有group by子句的情況下,基於索引優化Min、max操作或者對於MyISAM儲存引擎優化count(*),不必等到執行階段再進行計算,查詢執行計劃生成的階段即完成優化。
8、distinct:優化distinct操作,在找到第一匹配的元組後即停止找同樣值的動作。