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分割槽方式
droptable 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 partitionby 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操作,在找到第一匹配的元組後即停止找同樣值的動作。 |