Mysql索引優化
阿新 • • 發佈:2020-08-09
Mysql索引優化
準備資料
-
建立一個測試用表
-
往表中插入10w條隨機資料的儲存過程
CREATE DEFINER=`root`@`%` PROCEDURE `insert_tbl`(in max_num int(10)) BEGIN declare i int default 0; set autocommit=0; repeat set i=i+1; insert into test_tbl (id,user_name,access_time,ip_addr,user_group)values(null,rand_string(rand()*7+3),rand_datetime(2015,5),rand_ip(),rand_num()); until i = max_num end repeat; commit; END
1)隨機字串函式(param表示生成字串的長度)
CREATE DEFINER=`root`@`%` FUNCTION `rand_string`(n int) RETURNS varchar(255) CHARSET latin1 BEGIN declare chars_str varchar(52) 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
2)隨機日期函式(param1表示最小,param2表示年份波動)
CREATE DEFINER=`root`@`%` FUNCTION `rand_datetime`(n year, num int) RETURNS varchar(255) CHARSET latin1 BEGIN declare aDatetime varchar(255) default ''; set aDatetime=concat(concat(n+floor((rand()*num)),'-', lpad(floor(2 + (rand() * 11)),2,0),'-', lpad(floor(3 + (rand() * 25)),2,0)), #最多到每月27號 ' ', concat(lpad(floor(0 + (rand() * 23)),2,0),':', lpad(floor(0 + (rand() * 60)),2,0),':', lpad(floor(0 + (rand() * 60)),2,0))); return aDatetime; END
3)隨機ip函式
CREATE DEFINER=`root`@`%` FUNCTION `rand_ip`() RETURNS varchar(255) CHARSET latin1
BEGIN
declare ip varchar(255) default '';
set ip = concat(FLOOR(100 + RAND() * 26), '.',
FLOOR(0 + RAND() * 256), '.',
FLOOR(0 + RAND() * 256), '.',
FLOOR(0 + RAND() * 256));
return ip;
END
4)隨機數字函式(已指定範圍在0-127,可以修改為傳參指定)
CREATE DEFINER=`root`@`%` FUNCTION `rand_num`() RETURNS int(8)
BEGIN
declare i int default 0;
set i = floor(0+rand()*128);
return i;
END
索引型別
查看錶的索引
增加索引
-- primary key每個表只允許存在一個,而且不重複不為空
alter table test_tbl add unique unique_index(ip_addr) #唯一索引,不許重複,允許為空
alter table test_tbl add index normal_index(user_name) #普通索引,沒有限制
alter table test_tbl add index union_index(user_name,access_time,user_group) #組合索引,包含多列避免回表
刪除某個索引
drop index index_name on test_tbl;
Explain執行計劃
explain列的含義
列項 | 含義 |
---|---|
id | 每個select關鍵字對應一個唯一id |
select_type | 查詢型別 |
partitions | 匹配的分割槽資訊 |
type | 單表的訪問方法 |
possible_keys | 可能用到的索引 |
key | 實際使用的索引 |
key_len | 實際使用的索引長度 |
ref | 索引的哪一列被使用 |
rows | 預估需要讀取的記錄數目 |
filtered | 經過濾剩餘的記錄條數百分比 |
extra | 額外資訊 |
說明:
select_type欄位 | 含義 |
---|---|
SIMPLE | 簡單查詢,不包含子查詢或union查詢 |
PRIMARY | 查詢中包含複雜的子部份,最外層標記為主查詢 |
SUBQUERY | 在select或where中包含子查詢 |
DERIVED | 在from中的子查詢標記為衍生,查詢結果存放在臨時表中 |
UNION | select出現在union之後 |
UNION RESULT | 從union結果表中獲取查詢結果 |
type欄位 | 含義 |
---|---|
null | 優化階段分解查詢語句,執行階段不訪問表或索引 |
system | 表中只有一條記錄(等同於系統表) |
const | 通過索引一次命中(如where後跟主鍵條件) |
eq_ref | 唯一性索引掃描 |
ref | 非唯一性索引掃描,可能會找到符合條件的索引行 |
ref_or_null | 類似ref但可以搜尋null |
index_merge | 索引合併 |
range | 只檢索給定範圍的行(between,><,in) |
index | 遍歷索引樹 |
all | 從硬碟中遍歷全表已找到匹配行 |
extra欄位:
Extra欄位 | 含義 |
---|---|
Using filesort | 對資料作外部排序,而不是按表內索引順序讀取 |
Using temporary | 使用臨時表儲存中間結果(排序,分組) |
Using index | 使用覆蓋索引(同時有using where表示索引不是讀取資料而是查詢鍵值) |
Using where | 條件查詢 |
Using join buffer | 使用連線快取 |
impossible where | where子句總為false |
distinct | 一旦找到匹配行就不再搜尋 |
select tables optimized away | 沒有遍歷就返回資料 |
索引優化原則
- 不以萬用字元開頭
- 資料無隱式轉化
所以字串要用引號
- 索引列上作計算,函式,型別轉化等將使索引失效
-
覆蓋索引
select值取出需要的列,儘量避免select *。另外可將查詢列加入形成組合索引避免回表
-
最佳左字首法則
where條件從索引的最左前列開始且不跳過索引列使用,下列情況索引失效
-
範圍列右邊的索引列失效
關注key_len長度