1. 程式人生 > 實用技巧 >Mysql索引優化

Mysql索引優化

Mysql索引優化

準備資料

  1. 建立一個測試用表

  1. 往表中插入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 沒有遍歷就返回資料

索引優化原則

  1. 不以萬用字元開頭

  1. 資料無隱式轉化

所以字串要用引號

  1. 索引列上作計算,函式,型別轉化等將使索引失效

  1. 覆蓋索引

    select值取出需要的列,儘量避免select *。另外可將查詢列加入形成組合索引避免回表

  2. 最佳左字首法則

    where條件從索引的最左前列開始且不跳過索引列使用,下列情況索引失效

  1. 範圍列右邊的索引列失效

    關注key_len長度