一、慢查詢
1、慢查詢日誌
是指 mysql 記錄所有執行超過long_query_time
參數設定的時間閾值的 SQL 語句的日誌。
2、慢查詢配置
# 默認 10 秒,這裏爲了演示方便設置爲 0
set global long_query_time=0;
#W開啓慢查詢日誌
set GLOBAL slow_query_log = 1;
# 項目開發中日誌只能記錄在日誌文件中,不能記表中
set global log_output='FILE,TABLE'
# 查看慢查詢日誌信息
cat /usr/local/mysql/data/mysql-slow.log
3、慢查詢日誌解析
- 第一行:用戶名 、用戶的 IP 信息、線程 ID 號
- 第二行:執行花費的時間【單位:毫秒】
- 第三行:執行獲得鎖的時間
- 第四行:獲得的結果行數
- 第五行:掃描的數據行數
- 第六行:這 SQL 執行的具體時間
- 第七行:具體的 SQL 語句
4、慢查詢分析
慢查詢的日誌記錄非常多,要從裏面找尋一條查詢慢的日誌並不是很容易的事情,一般來說都需要一些工具輔助才能快速定位到需要優化的 SQL 語句。
4.1Mysqldumpshow
mysqldumpshow -s r -t 10 slow-mysql.log
-s order (c,t,l,r,at,al,ar)
c:總次數
t:總時間
l:鎖的時間
r:總數據行
at,al,ar :t,l,r 平均數 【例如:at = 總時間/總次數】
-t top 指定取前面幾條作爲結果輸出
# 按照時間排序,取出前10條記錄
mysqldumpslow -s t -t 10 /usr/local/mysql/data/mysql-slow.log
二、索引
1、mysql索引B+tree
1.1定義
- 數據只存儲在葉子節點上,非葉子節點只保存索引信息;
◦ 非葉子節點(索引節點)存儲的只是一個 Flag,不保存實際數據記錄;
◦ 索引節點指示該節點的左子樹比這個 Flag 小,而右子樹大於等於這個 Flag - 葉子節點本身按照數據的升序排序進行鏈接(串聯起來);
◦ 葉子節點中的數據在 物理存儲上是無序 的,僅僅是在 邏輯上有序 (通過指針串在一起);
1.2 作用
- 在塊設備上,通過B+樹可以有效的存儲數據;
- 所有記錄都存儲在葉子節點上,非葉子(non-leaf)存儲索引(keys)信息;
- B+樹含有非常高的扇出(fanout),通常超過100,在查找一個記錄時,可以有效的減少IO操作;
1.3B+tree操作
2、索引分類
- 普通索引:即一個索引只包含單個列,一個表可以有多個單列索引
- 唯一索引:索引列的值必須唯一,但允許有空值 複合索引:即一個索引包含多個列
- 聚簇索引(聚集索引):並不是一種單獨的索引類型,而是一種數據存儲方式。具體細節取決 於不同的實現,InnoDB 的聚簇索引其實就是在同一個結構中保存了 B-Tree 索引(技術上來說 是B+Tree)和數據行。
- 非聚簇索引:不是聚簇索引,就是非聚簇索引
# 查看索引
SHOW INDEX FROM table_name\G
# 創建索引
CREATE [UNIQUE ] INDEX indexName ON mytable(columnname(length));
ALTER TABLE 表名 ADD [UNIQUE ] INDEX [indexName] ON (columnname(length))
# 刪除索引
DROP INDEX [indexName] ON mytable;
三、執行計劃
使用 EXPLAIN 關鍵字可以模擬優化器執行 SQL 查詢語句,從而知道 MySQL 是 如何處理你的 SQL 語句的。分析你的查詢語句或是表結構的性能瓶頸。
1、執行計劃詳解
四、sql優化
1、儘量全值匹配
當建立了索引列後,能在 wherel 條件中使用索引的儘量所用。
2、最佳坐前綴原則法則
如果索引了多列,要遵守最左前綴法則。指的是查詢從索引的最左前列開始並且不跳過索引中的列。
3、不在索引列上做任何操作
不在索引列上做任何操作(計算、函數、(自動 or 手動)類型轉換),會導致索引失效而轉向 全表掃描
4、範圍條件放最後
中間有範圍查詢會導致後面的索引列全部失效
5、覆蓋索引儘量用
6不等於要甚用
mysql 在使用不等於(!= 或者<>)的時候無法使用索引會導致全表掃描,如果定要需要使用不等於,請用覆蓋索引
7、Null/Not 有影響
- 在字段爲 not null 的情況下,使用 is null 或 is not null 會導致索引失效
- 自定義爲NULL或者不定義,Is not null 的情況會導致索引失效
解決方式:覆蓋索引
8Like 查詢要當心
like 以通配符開頭(’%abc…’)mysql 索引失效會變成全表掃描的操作
解決方式:覆蓋索引
EXPLAIN select name,age,pos from staffs where name like ‘%july%’
9、字符類型加引號
字符串不加單引號索引失效
10、OR改UNION效率高
# 索引失效
EXPLAIN
select * from staffs where name='July' or name = 'z3'
EXPLAIN
select * from staffs where name='July' UNION
select * from staffs where name = 'z3'
解決方式:覆蓋索引
EXPLAIN
select name,age from staffs where name='July' or name = 'z3'
解決方式:覆蓋索引
EXPLAIN
select name,age from staffs where name='July' or name = 'z3'
記憶總結:
- 全職匹配我最愛,最左前綴要遵守;
- 帶頭大哥不能死,中間兄弟不能斷; 索引列上少計算,範圍之後全失效;
- LIKE百分寫最右,覆蓋索引不寫*;
- 不等空值還有OR,索引影響要注意;
- VAR 引號不可丟, SQL 優化有訣竅。
五、批量導入
LOAD DATA INFLIE
使用 LOAD DATA INFLIE ,比一般的 insert 語句快 20 倍
// 將product_info數據導出
select * into OUTFILE 'D:\\product.txt' from product_info
// 導入到product_info2中
load data INFILE 'D:\\product.txt' into table product_info2
load data INFILE '/soft/product3.txt' into table product_info2
200萬條數據,17s
show VARIABLES like 'secure_file_priv'
- secure_file_priv 爲 NULL 時,表示限制 mysqld 不允許導入或導出。
- secure_file_priv 爲 /tmp 時,表示限制 mysqld 只能在/tmp 目錄中執行導入導出,其他目錄不能執行。
- secure_file_priv沒有值時,表示不限制mysqld在任意目錄的導入導出。