mysql高階優化學習
一、mysql的架構
①mysql的優勢
主要體現在儲存引擎的架構上,外掛式的儲存引擎架構將查詢處理和其它的系統任務以及資料的儲存提取想分離。這種架構可以根據業務的需求和實際需求選擇合適的 儲存引擎。
②架構介紹詳細
二、mysql儲存引擎介紹
①檢視儲存引擎的命令
②MyISAM和InnoDB對比
阿里使用的是:percona的XtraDB,XtraDB比innodb效能更好完全可以取代XtraDB
三、SQL效能下降原因
①執行時間長
②等待時間長
|--查詢語句寫的爛
|--索引失效
|--關聯查詢太多join(設計缺陷或不得已的需求)
|--伺服器調優及各個引數設定(緩衝、執行緒池)
四、機器讀sql的順序:
五、mysql的七種join
六、索引
①索引:
索引(index)是幫助mysql高效獲得資料的資料結構。
是排好序的快速查詢資料結構。
②索引的儲存
索引本身也很大,不可能全部儲存在記憶體中,因此索引往往以索引檔案的形式儲存在磁碟上
③索引的分類
平常所說的索引,一般指B樹(多路搜尋索引,並不一定是二叉樹)結構組織的索引,唯一索引預設都是B+樹索引,除了B+樹 還有雜湊索引(hash index)
④索引的功能和優勢:
|--排序和查詢,降低io消耗和cpu消耗
⑤索引的劣勢:
|--索引是一張表儲存了主鍵和索引列,指向記錄,是佔用空間的
|--降低更新表的速度,插入和刪除會重新建索引
|-- 最優秀的索引需要花時間去摸索
⑥索引的分類和建立
索引分類:唯一索引(unique)、普通索引(Normal)、組合索引、全文索引
索引方法分類:BTREE、HASH
⑦索引結構與檢索原理
1、結構:
2、檢索原理
3、適合建索引
4、不適合建索引
建索引的參考公式:
七、進行sql語句優化(Explain)
①、mysql的查詢優化解析器(mysql Query Optimizer)工作原理
②、MySQL常見瓶頸
③執行計劃(Explain)
1、是什麼(檢視執行計劃)
使用EXPLAIN關鍵字可以模擬優化器執行SQL語句,從而知道MySQL是
如何處理你的SQL語句的。分析你的查詢語句或是結構的效能瓶頸
2、能幹嘛
3、怎麼玩
(1)Explain+SQL語句
(2)執行計劃包含的資訊
4、各個欄位解釋
(1) id:select查詢的序列號,表示查詢中執行select執行子句或操作表的順序
①id相等的情況
表示執行順序由上到下
例:
EXPLAIN SELECT
*
FROM
tb_item_desc t1,
tb_item_param_item t2,
tb_item t3
WHERE
t1.item_id = t2.item_id
AND t2.item_id = t3.id;
結果:
順序是:表t2,表t1,表t3
②id不等
如果是子查詢,id的序號會遞增,id值越大優先順序越高,越先被執行
先執行雞蛋黃,後雞蛋清,再是雞蛋殼,像是小雞孵化,先執行子查詢
③id即相等,又不等
(2) select_type
(3) table
顯示這一行的資料是關於哪張表的
(4) type
system:
const:
條件等於一個常 量值
eq_ref:
連表條件匹配,只有一條記錄匹配
ref:
條件查詢,匹配的有很多條
rang:
主鍵在一個範圍內
index:
全索引查詢
(4) possible_keys和key
例如:酒宴,應到多少人(possible_key),實到多少人(key)
下例中:因為查詢的是兩個欄位的組合索引,整合匹配上索引,但是mysql優化器沒有檢測到查詢單個欄位可以用到寫索引,所以possible_keys是null,key是組合索引
(5)key_len
(6)ref
(7)rows
每張表有多少行被優化器查詢
(8)Extra
Using filesort
因為去掉了一層的索引,直接用二層的索引進行排序,所以mysql不知道索引的排法,所以重新進行檔案內排序
Using temporary
同樣是索引沒有覆蓋
④建索引的案例分析
單表優化案例 1、
原因解釋:
第一次索引建立在category_id,comments,views上,因為第二個索引是rang型別,所以使得views這個索引失效,
第二次建立的索引是category_id和views,順帶著把常量category_id帶上了
雙表優化案例2:
對於左右連線的表建索引技巧:
左連線,就把索引健在右表的相應欄位上
右連線,就把索引健在左表相應的欄位上
原因解釋:
因為如果是左連線的話,左表的資料是確定的,右表是不確定的,索引應該在右表上建索引使得優化器更快的匹配資料。
三表優化案例3:
和雙表類似
調高JoinBuffer的配置
⑤、索引失效的原因及避免訣竅
1、全值匹配索引
2、最佳左字首法則
解釋:如果跳過開頭,後面全部的索引就斷檔了,如果跳過中間,開頭索引不斷檔,後面的索引斷檔
3、不要在索引列上做任何的操作
4、儲存引擎不能使用索引中範圍條件右邊的列
5、儘量使用覆蓋索引
(查詢的列儘量都在索引列的覆蓋範圍之內)
6、!=或則<>會使索引失效
7、is null 和 is not null 會使索引失效
8、解決like ‘%……%’索引失效
(1)like 'abc%' 在後面加%號
(2)使用索引覆蓋
9、字串不加單引號會使索引失效
10、用or也會是索引失效
11、小總結
⑥索引相關面試題分析
題目1、
都是常量,跟索引的順序不同
總結:條件的順序和索引的順序不一樣,但是查詢的效果是一樣的,但是最好要一樣,因為mysql優化器會進行一次轉換,轉換成和索引順序一樣的。
題目2、
總結建議:
八、查詢擷取分析(線上優化)
總概括(調優的四個維度):
維度一:慢查詢擷取sql
維度二:Explain分析
維度三:Profile分析
維度四:資料庫引數修改調優
①查詢優化
1、小表驅動大表,類似於巢狀查詢
類比mysql,建議用第一個迴圈的寫法,因為第一個迴圈只需要5次IO操作,第二個迴圈需要1000次的IO操作
2、關於order by的效能處理
場景:如果order by 的索引沒有用上,而進行了filesort的話,需調整引數進行優化
filesort的雙路排序:
雙路排序:是首先根據相應的條件取出相應的排序欄位和可以直接定位行資料的行指標資訊,然後在sort buffer 中進行排序,排完以後再次讀取資料。
單路排序:是一次性取出滿足條件行的所有欄位,然後在sort buffer中進行排序。
二 優化order by
當無法避免排序操作時,又該如何來優化呢?很顯然,優先選擇第一種using index 的排序方式,在第一種方式無法滿足的情況下,儘可能讓 MySQL 選擇使用第二種單路演算法來進行排序。這樣可以減少大量的隨機IO操作,很大幅度地提高排序工作的效率。
1 加大 max_length_for_sort_data 引數的設定
在 MySQL 中,決定使用老式排序演算法還是改進版排序演算法是通過引數 max_length_for_ sort_data 來決定的。當所有返回欄位的最大長度小於這個引數值時,MySQL 就會選擇改進後的排序演算法,反之,則選擇老式的演算法。所以,如果有充足的記憶體讓MySQL 存放須要返回的非排序欄位,就可以加大這個引數的值來讓 MySQL 選擇使用改進版的排序演算法。
2 去掉不必要的返回欄位
當記憶體不是很充裕時,不能簡單地通過強行加大上面的引數來強迫 MySQL 去使用改進版的排序演算法,否則可能會造成 MySQL 不得不將資料分成很多段,然後進行排序,這樣可能會得不償失。此時就須要去掉不必要的返回欄位,讓返回結果長度適應 max_length_for_sort_data 引數的限制。
3 增大 sort_buffer_size 引數設定
這個值如果過小的話,再加上你一次返回的條數過多,那麼很可能就會分很多次進行排序,然後最後將每次的排序結果再串聯起來,這樣就會更慢,增大 sort_buffer_size 並不是為了讓 MySQL選擇改進版的排序演算法,而是為了讓MySQL儘量減少在排序過程中對須要排序的資料進行分段,因為分段會造成 MySQL 不得不使用臨時表來進行交換排序。
但是這個值不是越大越好:
1 Sort_Buffer_Size 是一個connection級引數,在每個connection第一次需要使用這個buffer的時候,一次性分配設定的記憶體。
2 Sort_Buffer_Size 並不是越大越好,由於是connection級的引數,過大的設定+高併發可能會耗盡系統記憶體資源。
3 據說Sort_Buffer_Size 超過2M的時候,就會使用mmap() 而不是 malloc() 來進行記憶體分配,導致效率降低。
單路排序:
結論及引申:
3、GROUP BY關鍵字優化
②慢查詢日誌
1、慢查詢日誌是什麼?
2、怎麼玩?
(1)說明
(2)檢視是否開啟及如何開啟
檔案型別的配置:
(3)日誌分析工具mysqldumpslow
③用Show Profile進行sql分析
1、批量插入資料指令碼,插入1000w資料
(1)建表
#新建庫
create database bigData;
use bigData;
#1建表dept
CREATE TABLE `dept` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`deptno` mediumint(9) NOT NULL,
`dname` varchar(20) NOT NULL,
`loc` varchar(13) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
#2建表emp
CREATE TABLE `emp` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`empno` mediumint(9) NOT NULL DEFAULT '0',
`ename` varchar(20) NOT NULL,
`job` varchar(9) NOT NULL,
`mgr` mediumint(9) NOT NULL,
`hiredate` date NOT NULL,
`sal` decimal(7,2) NOT NULL,
`comm` decimal(7,2) NOT NULL,
`deptno` mediumint(9) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
(2)首先設定log_bin_trust_function_creators的引數
-------------------------------------------------------------------------------------
MySQL引數log_bin_trust_function_creators介紹
簡單介紹一下,當二進位制日誌啟用後,這個變數就會啟用。它控制是否可以信任儲存函式建立者,不會建立寫入二進位制日誌引起不安全事件的儲存函式。如果設定為0(預設值),使用者不得建立或修改儲存函式,除非它們具有除CREATE ROUTINE或ALTER ROUTINE特權之外的SUPER許可權。 設定為0還強制使用DETERMINISTIC特性或READS SQL DATA或NO SQL特性宣告函式的限制。 如果變數設定為1,MySQL不會對建立儲存函式實施這些限制。 此變數也適用於觸發器的建立。
設定辦法:
-------------------------------------------------------------------------------------------
(3)建立函式,保證每條資料都不同
隨機產生字串
delimiter $$
CREATE FUNCTION rand_string(n INT) RETURNS VARCHAR(255)
BEGIN
DECLARE chars_str VARCHAR(100) DEFAULT 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
DECLARE return_str VARCHAR(255) DEFAULT '';
DECLARE i INT DEFAULT 0;
WHILE i<n DO
SET return_str = CONCAT(return_str,SUBSTRING(chars_str,FLOOR(1+RAND()*52),1));
SET i= i+1;
END WHILE;
RETURN return_str;
END $$
隨機產生部門編號
delimiter $$
CREATE FUNCTION rand_num() RETURNS INT(5)
BEGIN
DECLARE i INT DEFAULT 0;
SET i = FLOOR(100+RAND()*10);
RETURN i;
END $$
(4)建立儲存過程
插入員工表的儲存過程
delimiter $$
CREATE PROCEDURE inset_emp(IN START INT(10),IN max_num INT(10))
BEGIN
DECLARE i INT DEFAULT 0;
SET autocommit = 0;
REPEAT
SET i = i+1;
INSERT INTO emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) VALUES((START+i),rand_string(6),'SALESMAN',0001,CURDATE(),2000,400,rand_num());
UNTIL i = max_num
end REPEAT;
COMMIT;
END $$
插入部門表的儲存過程
delimiter $$
CREATE PROCEDURE insert_dept(IN START INT(10),IN max_num INT(10))
BEGIN
DECLARE i INT DEFAULT 0;
SET autocommit = 0;
REPEAT
SET i = i+1;
INSERT INTO dept(deptno,dname,loc)VALUES((START+i),rand_string(10),rand_string(8));
UNTIL i = max_num
END REPEAT;
COMMIT;
END $$
呼叫儲存過程
delimiter ;
CALL insert_dept(100,10);
delimiter;
CALL insert_emp(100001,500000);
2、 show profile的具體使用
(1)show profile是什麼?
可以分析出mysql執行的整個生命週期
(2)分析步驟
檢視mysql是否支援
開始分析
配置全域性查詢日誌(只在測試環境配,生產環境不要配)
配置啟用
編碼啟用
九、鎖理論
鎖的定義:
鎖的分類:
表鎖:
加讀鎖:
加寫鎖:
總結:
表鎖分析:
行鎖:
經常出現的異常:
行鎖分析:
優化建議:
頁鎖:
介於表鎖和行鎖之間
十、主從複製
①同步的原理
②複製的基本原則
③一主一重常見配置
①mysql的優化與執行
1、mysql會解析查詢,並建立內部資料結構(解析樹),然後對其進行各種優化,包